PyInstaller打包应用程序在控制台模式下工作正常,在窗口模式下崩溃

Bo *_*ich 5 python qt pyqt pyinstaller pyside

我正在使用Python和PySide构建一个相当复杂的应用程序.最后发布的那天即将到来,所以我想将这个应用程序构建为exe.

但是,我的手上有一个奇怪的问题.我过去使用过PyInstaller(顺便使用版本2),从来没有发生过这种情况.

基本上,当我使用--console标志构建应用程序时,它工作正常 - 但它打开控制台窗口.当我使用window flag(-w)构建应用程序时,它不能正常工作.它开始和一切,但有所有这些奇怪的故障.例如,加载文本文件通常会引发BadFileDescriptor错误(在控制台模式下不会发生),并且应用程序在执行某项任务后崩溃.更糟糕的是,任务是循环,并且第一次执行正常,但是当它再次开始工作时,它会崩溃.

当我查看minidump文件时,有一些关于QtGui4.dll文件的内存访问冲突的错误.同样,这在控制台模式下不会发生.

有人有主意吗?

Bak*_*riu 7

BadFileDescriptor误差和因此存储器访问冲突由以下事实引起stdout的在窗口模式下的应用程序的大小是固定的缓冲区.所以,如果你正在写stdout,要么printsys.stdout直接,一段时间后,你会看到这些错误.

你可以解决这个问题:

  1. 删除/评论出来的作品 stdout
  2. 使用logging而不是打印到stdout
  3. stdout在应用程序执行开始时重定向.这是需要更少代码的解决方案,即使我认为将调试语句移动到logging更好的选择.

要重定向,stdout您可以使用以下代码:

import sys
import tempfile
sys.stdout = tempfile.TemporaryFile()
sys.stderr = tempfile.TemporaryFile()
Run Code Online (Sandbox Code Playgroud)

就在执行程序之前.你也可以使用一些自定义对象将输出放在"日志"文件或其他任何东西,重要的是输出不应该填充固定大小的缓冲区.

例如,你可以做这样的事情,以便能够在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
Run Code Online (Sandbox Code Playgroud)

这种方法的缺点是对每一行print执行更多调用stdout.write:

>>> print 'test'
DEBUG:debug:test
DEBUG:debug:
Run Code Online (Sandbox Code Playgroud)

如果你想要,你可以避免这种行为写一个只用"满线" write调用的真正函数the_logger.debug.

无论如何,我认为这种解决方案应该只是暂时的,并且只能在将prints 移植到调用之前使用logging.debug.

(显然记录器应该写入文件而不是stdout为了避免错误.)