source: sasview/src/sas/qtgui/Utilities/SasviewLogger.py @ 5dba493

Last change on this file since 5dba493 was 5dba493, checked in by Torin Cooper-Bennun <torin.cooper-bennun@…>, 6 years ago

rework XStream to continue to write to stdout/stderr alongside redirection; make logging level setting consistent; make log configuration more consistent

  • Property mode set to 100644
File size: 3.3 KB
Line 
1import os
2import sys
3import logging
4
5from PyQt5.QtCore import *
6
7
8class XStream(QObject):
9    """
10    Imitates, loosely, an `io.TextIOWrapper` class in order to intercept
11    messages going to stdout and stderr.
12
13    To intercept messages to stdout, use:
14
15    .. code-block:: python
16       XStream.stdout().messageWritten.mySignalHandler()
17
18    All messages to stdout will now also be emitted to your handler. Use
19    `XStream.stderr()` in the same way to intercept stderr messages.
20
21    An additional function, `XStream.write_log()`, emits a message only to the
22    messageWritten signal, and not the stdout or stderr streams. It is intended
23    for separation of log handling between console and Qt, as reflected in the
24    name.
25    """
26    _stdout = None
27    _stderr = None
28    messageWritten = pyqtSignal(str)
29
30    _real_stream = None
31
32    def flush(self):
33        pass
34
35    def fileno(self):
36        return -1
37
38    def write(self, msg):
39        """
40        'msg' is emitted in the messageWritten signal, and is also written to
41        the original stream. This means stdout/stderr messages have been
42        redirected to a custom location (e.g. in-widget), but also reach
43        console output.
44
45        :param msg: message to write
46        :return: None
47        """
48        if(not self.signalsBlocked()):
49            self.messageWritten.emit(str(msg))
50        self._real_stream.write(msg)
51
52    def write_log(self, msg):
53        """
54        'msg' is only emitted in the messageWritten signal, not in the original
55        stdout/stderr stream, for the purposes of logging. Use in, e.g. a
56        custom logging handler's emit() function.
57
58        :param msg: message to write
59        :return: None
60        """
61        if(not self.signalsBlocked()):
62            self.messageWritten.emit(str(msg))
63
64    @staticmethod
65    def stdout():
66        """
67        Creates imitation of sys.stdout.
68        :return: An XStream instance that interfaces exactly like sys.stdout,
69                 but, has redirection capabilities through the
70                 messageWritten(str) signal.
71        """
72        if(not XStream._stdout):
73            XStream._stdout = XStream()
74            XStream._stdout._real_stream = sys.stdout
75            sys.stdout = XStream._stdout
76        return XStream._stdout
77
78    @staticmethod
79    def stderr():
80        """
81        Creates imitation of sys.stderr.
82        :return: An XStream instance that interfaces exactly like sys.stderr,
83                 but, has redirection capabilities through the
84                 messageWritten(str) signal.
85        """
86        if(not XStream._stderr):
87            XStream._stderr = XStream()
88            XStream._stderr._real_stream = sys.stderr
89            sys.stderr = XStream._stderr
90        return XStream._stderr
91
92
93class QtHandler(logging.Handler):
94    """
95    Version of logging handler "emitting" the message to custom stdout()
96    """
97    def __init__(self):
98        logging.Handler.__init__(self)
99
100    def emit(self, record):
101        record = self.format(record)
102        if record:
103            XStream.stdout().write_log('%s\n'%record)
104
105
106# Define the default logger
107logger = logging.getLogger()
108
109# Add the qt-signal logger
110handler = QtHandler()
111handler.setFormatter(logging.Formatter(
112    fmt="%(asctime)s - %(levelname)s: %(message)s",
113    datefmt="%H:%M:%S"
114))
115logger.addHandler(handler)
Note: See TracBrowser for help on using the repository browser.