-
Notifications
You must be signed in to change notification settings - Fork 0
/
boot_common.py
104 lines (98 loc) · 3.67 KB
/
boot_common.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
100
101
102
103
104
# Common py2exe boot script - executed for all target types.
# When we are a windows_exe we have no console, and writing to
# sys.stderr or sys.stdout will sooner or later raise an exception,
# and tracebacks will be lost anyway (see explanation below).
#
# We assume that output to sys.stdout can go to the bitsink, but we
# *want* to see tracebacks. So we redirect sys.stdout into an object
# with a write method doing nothing, and sys.stderr into a logfile
# having the same name as the executable, with '.log' appended.
#
# We only open the logfile if something is written to sys.stderr.
#
# If the logfile cannot be opened for *any* reason, we have no choice
# but silently ignore the error.
#
# It remains to be seen if the 'a' flag for opening the logfile is a
# good choice, or 'w' would be better.
#
# More elaborate explanation on why this is needed:
#
# The sys.stdout and sys.stderr that GUI programs get (from Windows) are
# more than useless. This is not a py2exe problem, pythonw.exe behaves
# in the same way.
#
# To demonstrate, run this program with pythonw.exe:
#
# import sys
# sys.stderr = open("out.log", "w")
# for i in range(10000):
# print i
#
# and open the 'out.log' file. It contains this:
#
# Traceback (most recent call last):
# File "out.py", line 6, in ?
# print i
# IOError: [Errno 9] Bad file descriptor
#
# In other words, after printing a certain number of bytes to the
# system-supplied sys.stdout (or sys.stderr) an exception will be raised.
#
import sys
import os
import ctypes
##print("this is boot_common")
##print("PATH", repr(sys.path[0]), "thats it.")
if sys.frozen == "windows_exe":
class Stderr(object):
_file = None
_error = None
def write(self, text, alert=ctypes.windll.user32.MessageBoxW,
fname=os.path.splitext(sys.executable)[0] + '.log'):
if self._file is None and self._error is None:
import atexit, os, sys
try:
self._file = open(fname, 'a')
except Exception as details:
self._error = details
atexit.register(alert, 0,
"The logfile '%s' could not be opened:\n %s" % \
(fname, details),
"Errors in %r" % os.path.basename(sys.executable),
0)
else:
atexit.register(alert, 0,
"See the logfile '%s' for details" % fname,
"Errors in %r" % os.path.basename(sys.executable),
0)
if self._file is not None:
self._file.write(text)
self._file.flush()
def flush(self):
if self._file is not None:
self._file.flush()
sys.stderr = Stderr()
del Stderr
class Blackhole(object):
softspace = 0
def write(self, text):
pass
def flush(self):
pass
sys.stdout = Blackhole()
del Blackhole
del sys, ctypes
## # Disable linecache.getline() which is called by
## # traceback.extract_stack() when an exception occurs to try and read
## # the filenames embedded in the packaged python code. This is really
## # annoying on windows when the d: or e: on our build box refers to
## # someone elses removable or network drive so the getline() call
## # causes it to ask them to insert a disk in that drive.
## import linecache
## def fake_getline(filename, lineno, module_globals=None):
## return ''
## linecache.orig_getline = linecache.getline
## linecache.getline = fake_getline
##
##del linecache, fake_getline