PyInstaller打包的应用程序在控制台模式下工作正常,在窗口模式下崩溃
问题内容:
我正在使用Python和PySide构建一个相当复杂的应用程序。终于,发布的日子快到了,所以我想将此应用程序构建为exe。
但是,我手上有一个奇怪的问题。我过去曾经使用过PyInstaller(顺便使用版本2),但从未发生过这种情况。
基本上,当我使用--console
标志构建应用程序时,它可以正常工作-
但它会打开控制台窗口。当我使用窗口标志(-w
)构建应用程序时,它无法正常工作。它开始了一切,但是所有这些怪异的故障。例如,加载文本文件通常会引发BadFileDescriptor
错误(在控制台模式下不会发生),并且执行特定任务后应用程序崩溃。更糟糕的是该任务是一个循环,并且第一次执行良好,但是当它再次开始工作时会崩溃。
当我查看minidump文件时,发现一些有关QtGui4.dll文件的内存访问冲突的错误。同样,在控制台模式下不会发生这种情况。
谁有想法?
问题答案:
的BadFileDescriptor
误差和因此存储器访问冲突由以下事实引起stdout
的在窗口模式下的应用程序是一个固定大小的缓冲区。因此,如果您正在stdout
使用print
或sys.stdout
直接写入,一段时间后您会看到这些错误。
您可以通过以下方法解决此问题:
- 删除/注释上的著作
stdout
- 使用
logging
而不是打印到标准输出 stdout
在应用程序执行开始时进行重定向。尽管我认为将调试语句移至logging
将是更好的选择,但这是一种解决方案,只需更改较少的代码。
要重定向,stdout
您可以使用以下代码:
import sys
import tempfile
sys.stdout = tempfile.TemporaryFile()
sys.stderr = tempfile.TemporaryFile()
在执行程序之前。您还可以使用一些自定义对象将输出放入“ log”文件或其他文件中,重要的是输出不应填充固定大小的缓冲区。
例如,您可以执行以下操作以在logging
不更改太多代码的情况下利用模块:
import sys
import logging
debug_logger = logging.getLogger('debug')
debug_logger.write = debug_logger.debug #consider all prints as debug information
debug_logger.flush = lambda: None # this may be called when printing
#debug_logger.setLevel(logging.DEBUG) #activate debug logger output
sys.stdout = debug_logger
这种方法的缺点是对每一行print
执行更多的调用stdout.write
:
>>> print 'test'
DEBUG:debug:test
DEBUG:debug:
如果愿意,可以避免编写纯write
函数the_logger.debug
仅用“全行”调用的实际行为。
无论如何,我认为这类解决方案应该只是临时的,并且只能在将print
s移植到to的调用之前使用logging.debug
。
(显然,记录器应写入文件,而不是stdout
避免错误。)