7

我正在使用 Python 和 PySide 构建一个相当复杂的应用程序。终于发布的日子快到了,所以我想将此应用程序构建为 exe。

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

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

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

有人有想法么?

4

1 回答 1

9

错误和因此的内存访问冲突是由窗口模式下的应用程序是一个固定大小的缓冲区BadFileDescriptor这一事实引起的。因此,如果您正在使用或直接stdout写入,一段时间后您会看到这些错误。stdoutprintsys.stdout

您可以通过以下方式解决此问题:

  1. 删除/注释掉关于stdout
  2. 使用logging而不是打印到标准输出
  3. stdout在应用程序执行开始时重定向。这是需要更改的代码更少的解决方案,即使我认为将调试语句移至logging将是更好的选择。

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

import sys
import tempfile
sys.stdout = tempfile.TemporaryFile()
sys.stderr = tempfile.TemporaryFile()

就在执行你的程序之前。您还可以使用一些自定义对象将输出放入“日志”文件或其他文件中,重要的是输出不应填充固定大小的缓冲区。

例如,您可以执行类似这样的操作,以便能够在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

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

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

于 2012-11-17T12:49:27.280 回答