-
Notifications
You must be signed in to change notification settings - Fork 0
/
ProgressHandler.py
executable file
·99 lines (75 loc) · 3.18 KB
/
ProgressHandler.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#!/usr/bin/env python3
"""
A StreamHandler for the logging module that supports progress indicators.
Based on Ethan Furman's answer at
https://stackoverflow.com/questions/3118059/how-to-write-custom-python-logging-handler
"""
import logging
import curses.ascii
class ProgressHandler(logging.StreamHandler):
"""
A logging console handler that supports staying on the same line, as well as
going back to redraw lines.
The handler supports two 'extra' attributes:
- same_line If set, no terminator will be added at the end of the
line.
- overwrite If set, the cursor will be rewound to the start of the
message, allowing the message to be overwritten. This is
useful for drawing progress bar backgrounds.
"""
on_same_line = False
overwriting = False
def emit(self, record):
try:
msg = self.format(record)
stream = self.stream
same_line = hasattr(record, 'same_line')
overwrite = hasattr(record, 'overwrite')
# Add an endline character if we start a new line, and we're in
# same-line-mode
if self.on_same_line and not (same_line or self.overwriting):
stream.write(self.terminator)
# If we're writing on the same line, only write the message and not
# the context information
if self.on_same_line:
msg = record.getMessage()
# Write the actual message
stream.write(msg)
# if it's in overwrite mode, rewind the cursor over the message
if overwrite:
stream.write(('%c' % curses.ascii.BS ) * len(record.getMessage()))
self.overwriting = True
else:
self.overwriting = False
# remember if the next message is to go on the same line
if same_line or overwrite:
self.on_same_line = True
# end the line if the next message doesn't go on the same line
else:
stream.write(self.terminator)
self.on_same_line = False
self.flush()
except (KeyboardInterrupt, SystemExit):
raise
except:
self.handleError(record)
if __name__ == '__main__':
import time
progress_handler = ProgressHandler()
logging.basicConfig(level=logging.DEBUG, handlers=[progress_handler])
logging.info("Regular message")
logging.info("Messages on the same line: ", extra={'same_line':True})
for i in range(5):
logging.info('%i ', i, extra={'same_line':True})
time.sleep(.2)
logging.info("A regular message automatically adds a trailing newline")
logging.info("This message can be overwritten", extra={'overwrite':True})
time.sleep(1)
logging.info("Now the message has been replaced")
logging.info("Progress: [", extra={'same_line':True})
logging.info(" ]",
extra={'overwrite':True, 'same_line':True})
for i in range(40):
logging.info('=', extra={'same_line':True})
time.sleep(.1)
logging.info("DONE")