1 """
2 Capture stdout or stderr messages to a log file
3
4 Based on code by Greg Pinero (Primary Searcher)
5
6 Capture print statments and write them to a log file
7 but still allow them to be printed on the screen.
8 """
9 import sys, os
10 import time
11 import types
12
14 """
15 This class implements a write-method and can therefore replace a stream
16 such as sys.stderr or sys.stdout. The write method first writes the text
17 to a log file, then passes it on to the original stream.
18 """
20 self.stream = stream
21 self.logfiles = []
22 self.logfilenames = []
23 self.indent = None
24 self.timeStamp = None
25 self.timeStampDuplicates = False
26 self.prevTime = None
27 self.newLine = True
28 self.buffer = ""
29
30 - def setLog(self, logfile=None):
31 if logfile != None:
32 self.logfiles = [logfile]
33 self.logfilenames = [logfile.name]
34 else:
35 self.logfiles = []
36 self.logfilenames = []
37
39 self.logfiles.append(logfile)
40 self.logfilenames.append(logfile.name)
41
42 - def removeLog(self, logfileName, streamName):
43 logfilesToKeep = []
44 logfilenamesToKeep = []
45 removed = None
46 removedName = None
47 for i in range(len(self.logfiles)):
48 if self.logfilenames[i] != logfileName:
49 logfilesToKeep.append(self.logfiles[i])
50 logfilenamesToKeep.append(self.logfilenames[i])
51 else:
52 removed = self.logfiles[i]
53 removedName = self.logfilenames[i]
54 self.logfiles = logfilesToKeep
55 self.logfilenames = logfilenamesToKeep
56
57 if removedName != None:
58 print >> sys.stderr, "Stopped logging", streamName, "to", removedName
59 else:
60 print >> sys.stderr, "Log not open for ", streamName + ":", logfileName
61 return removed
62
65
67 self.timeStamp = format
68 self.timeStampDuplicates = duplicates
69
71 """
72 Write directly to the stream without adding to the log file
73 """
74 self.stream.write(text)
75
77 """
78 Write directly to the log file without sending the input to the stream
79 """
80 for logfile in self.logfiles:
81 if filename == None or logfile.name == filename:
82 logfile.write(text)
83 logfile.flush()
84
86 if text == None or text == "":
87 return
88 """
89 Send the text to the stream after optionally writing it to the log file.
90 """
91 if self.indent != None:
92 if self.newLine:
93 text = self.indent + text
94 lastChar = text[-1]
95 text = text[:-1]
96 if lastChar == "\n":
97 self.newLine = True
98 else:
99 self.newLine = False
100 text = text.replace("\n","\n"+self.indent)
101 text += lastChar
102 self.stream.write(text)
103 self.stream.flush()
104 if len(self.logfiles) > 0:
105 for char in text:
106 if char == "\r":
107 self.buffer = ""
108 elif char == "\n":
109 timeString = time.strftime(self.timeStamp)
110 if timeString == self.prevTime and not self.timeStampDuplicates:
111 timeString = len(timeString) * " "
112 else:
113 self.prevTime = timeString
114 if self.timeStamp != None:
115 self.buffer = timeString + "\t" + self.buffer
116 for logfile in self.logfiles:
117 logfile.write(self.buffer + "\n")
118 self.buffer = ""
119 else:
120 self.buffer += char
121 for logfile in self.logfiles:
122 logfile.flush()
123
126
127 -def openLog(filename="log.txt", clear=False, logCmd=True):
128 if os.path.dirname(filename) != "" and not os.path.exists(os.path.dirname(filename)):
129 os.makedirs(os.path.dirname(filename))
130 setLog(filename, clear)
131 setTimeStamp("[%H:%M:%S %d/%m]", True)
132 logOpenTime = str(time.ctime(time.time()))
133 print >> sys.stderr, "Opening log", filename, "at", logOpenTime
134 logOpenMessage = "####### Log opened at " + str(time.ctime(time.time())) + " #######\n"
135 writeToLog(logOpenMessage, filename)
136 if logCmd:
137 writeToLog("Command line: " + " ".join(sys.argv) + "\n", filename)
138
147
151
155
156 -def setLog(filename=None, clear=False):
157 """
158 Replace sys.stderr and sys.stdout with a StreamModifier, capturing
159 all output for these streams to a log file while still passing it
160 to the original stream.
161 """
162 if not isinstance(sys.stdout, StreamModifier):
163 sys.stdout = StreamModifier(sys.stdout)
164 if not isinstance(sys.stderr, StreamModifier):
165 sys.stderr = StreamModifier(sys.stderr)
166 if filename != None:
167 if clear:
168 logfile = open(filename,"wt")
169 else:
170 logfile = open(filename,"at")
171 sys.stdout.addLog(logfile)
172 sys.stderr.addLog(logfile)
173
181
189