Commit d7ea6b9d authored by Saul Ibarra's avatar Saul Ibarra

Fix diverting std{out,err} when running frozen


When running frozen (ie, a Windows exe) we override sys.std{out,err} so the
output can be diverted to a file.  There was a problem with logging.Logger
instances which would get a reference to the original objecs and then find
then closed after our second replacement.

The solution is to override them very early, and this MUST be done BEFORE
importing the log module.  Then, when the file property is set the StringIO
will be drained into the file.
parent c34a12f5
...@@ -3,15 +3,12 @@ ...@@ -3,15 +3,12 @@
import os import os
import sys import sys
from application import log
def except_hook(exception_type, exception_value, traceback): def except_hook(exception_type, exception_value, traceback):
sys.__excepthook__(exception_type, exception_value, traceback) sys.__excepthook__(exception_type, exception_value, traceback)
sys.excepthook = except_hook # pyqt5 (>=5.5) will abort if an exception happens in python code when called from Qt, unless we define this sys.excepthook = except_hook # pyqt5 (>=5.5) will abort if an exception happens in python code when called from Qt, unless we define this
log.level.current = log.level.WARNING
frozen = hasattr(sys, 'frozen') frozen = hasattr(sys, 'frozen')
...@@ -33,7 +30,35 @@ if os.path.basename(script_dir) == 'bin' and os.path.exists(os.path.join(parent_ ...@@ -33,7 +30,35 @@ if os.path.basename(script_dir) == 'bin' and os.path.exists(os.path.join(parent_
if frozen: if frozen:
from StringIO import StringIO from StringIO import StringIO
sys.stdout = sys.stderr = StringIO()
class FakeStdout(object):
def __init__(self):
self._io = StringIO()
self._file = None
@property
def file(self):
return self._file
@file.setter
def file(self, f):
f.write(self._io.getvalue())
self._io.close()
self._file = f
def __getattr__(self, name):
if self._file is not None:
return getattr(self._file, name)
else:
return getattr(self._io, name)
sys.stdout = sys.stderr = FakeStdout()
# Import log last so the created StreamHandler instances have references
# to the replaced sys.std{out,err}
from application import log
log.level.current = log.level.WARNING
if __name__ == '__main__': if __name__ == '__main__':
......
...@@ -45,11 +45,8 @@ __all__ = ['Blink'] ...@@ -45,11 +45,8 @@ __all__ = ['Blink']
if hasattr(sys, 'frozen'): if hasattr(sys, 'frozen'):
output = sys.stdout
makedirs(ApplicationData.get('logs')) makedirs(ApplicationData.get('logs'))
sys.stdout = sys.stderr = open(ApplicationData.get('logs/output.log'), 'a', 0) sys.stdout.file = open(ApplicationData.get('logs/output.log'), 'a', 0)
sys.stdout.write(output.getvalue())
output.close()
class IPAddressMonitor(object): class IPAddressMonitor(object):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment