5 from logging import Logger, StreamHandler
9 """Defines several logs:
12 root log, which sends messages to `eval` and `test` logs
14 main log, initially a duplicated fd 2 (stderr)
16 public progress log, initially a duplicated fd 1 (stdout)
18 per-test log, initially no handler, to be directed to file like `{TEST}.log`
20 .. note:: Currently, the logs and fd's get never closed.
21 .. warning:: `Loggers.open_eval_log` changes global fd's 1 and 2 by default.
24 "Initialize loggers as described in class description."
25 Logger.__init__(self, '')
27 self.orig_stdout_fd = os.dup(1)
28 self.orig_stdout_file = os.fdopen(self.orig_stdout_fd, 'w', 0)
29 self.orig_stderr_fd = os.dup(2)
30 self.orig_stderr_file = os.fdopen(self.orig_stderr_fd, 'w', 0)
32 self.eval = Logger('eval')
33 self.eval.addHandler(StreamHandler(self.orig_stderr_file))
35 self.test = Logger('test')
36 self.test_handler = None
38 # user progress logger
39 self.user = Logger('user')
40 self.eval.addHandler(StreamHandler(self.orig_stdout_file))
42 self.addHandler(self.test)
43 self.addHandler(self.eval)
44 self.debug('Logging initialized.')
46 def open_user_log(self, filename, level=logging.INFO):
47 """Open user (progress) logfile. Leaves logging to stdout active."""
48 h = StreamHandler(open(filename, 'w', 0))
49 h.setFormatter(Formatter('%(message)s'))
50 self.user.setLevel(level)
51 self.user.addHandler(h)
52 self.user.debug('Logging started')
54 def open_eval_log(self, filename, level, redirect_fds = True):
56 Leaves logging to stderr active. If told to, redirects fd's 1 and 2 to this file.
57 Sets level of both `self.eval` and `self`."""
58 self.eval_file = open(filename, 'w', 0)
59 self.eval_handler = StreamHandler(self.eval_file)
60 self.eval_handler.setFormatter(Formatter('%(asctime)s [%(levelno)s] %(message)s'))
61 self.eval.addHandler(self.eval_handler)
63 os.dup2(self.eval_file.fileno(), 1)
64 os.dup2(self.eval_file.fileno(), 2)
65 self.eval.setLevel(level)
67 self.eval.debug('Logging started')
70 def open_test_log(self, filename, level):
71 """Open per-test log file, like "{TEST}.log". Also set handler level to `level`."""
72 self.debug('Opening per-test log %s' % filename)
75 self.test_file = open(filename, 'w')
76 self.test_handler = StreamHandler(self.test_file)
77 self.test.addHandler(self.test_handler)
78 self.test.setLevel(level)
79 self.test_handler.setFormatter(Formatter('%(asctime)s [%(levelno)s] %(message)s'))
80 self.test.debug('Logging started')
82 def close_test_log(self):
83 """Close per-test logfile, leaving only the null handler."""
85 self.test.info('Closing logfile' % filename)
86 self.test.removeHandler(self.test_handler)
87 self.test_handler = None
88 self.test_file.close()
90 def ddebug(self, msg, *args, **kwargs):
91 """Log with priority 5 (normal DEBUG is 10)"""
92 self.log(5, msg, *args, **kwargs)