PyInstaller 打包应用程序在控制台模式下工作正常,在窗口模式下崩溃 [英] PyInstaller packaged application works fine in Console mode, crashes in Window mode

查看:102
本文介绍了PyInstaller 打包应用程序在控制台模式下工作正常,在窗口模式下崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

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

有人有什么想法吗?

解决方案

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

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

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

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

导入系统导入临时文件sys.stdout = tempfile.TemporaryFile()sys.stderr = tempfile.TemporaryFile()

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

例如,您可以执行以下操作,以便在不更改太多代码的情况下利用 logging 模块:

导入系统导入日志debug_logger = logging.getLogger('debug')debug_logger.write = debug_logger.debug #将所有打印信息视为调试信息debug_logger.flush = lambda: None # 打印时可能会调用#debug_logger.setLevel(logging.DEBUG) #激活调试记录器输出sys.stdout = debug_logger

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

<预><代码>>>>打印测试"调试:调试:测试调试:调试:

如果您愿意,您可能可以避免这种行为,编写一个真正的 write 函数,该函数仅使用完整行"调用 the_logger.debug.

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

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

I am building a fairly complex application using Python and PySide. Finally the day of the release is nearing so I want to build this application as an exe.

However, I have a strange problem on my hands. I've used PyInstaller (using version 2 by the way) in the past and never had this happened to me.

Basically, when I build the application with the --console flag, it works fine - but it opens the console window. When I build the application with the window flag (-w), it doesn't work fine. It starts and everything, but there are all these weird glitches. For example, loading a text file often raises the BadFileDescriptor error (which doesn't happen in console mode), and the application crashes after performing a certain task. What's worse is that the task is a loop, and it performs fine the first time, but when it starts working again, it crashes.

When I looked at the minidump file there were some errors about memory access violation of QtGui4.dll file. Again, this doesn't happen in console mode.

Anyone have any ideas?

解决方案

The BadFileDescriptor error and the consequently memory access violation are caused by the fact that the stdout of applications in windowed mode is a fixed size buffer. So, if you have are writing to stdout, either with print or sys.stdout directly, after some time you'd see those errors.

You can fix this by:

  1. Removing/commenting out the writings on stdout
  2. Using logging instead of printing to stdout
  3. Redirecting stdout at the beginning of the execution of your application. This is the solution that requires less code to be changed, even though I think moving the debugging statements to logging would be the better choice.

To redirect stdout you can use this kind of code:

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

Just before executing your program. You can use also some custom object to put the output in "log" files or whatever, the important thing is that the output should not fill the fixed size buffer.

For example you could do something like this to be able to take advantage of the logging module without changing too much code:

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

The downside of this approach is that print executes more calls to stdout.write for each line:

>>> print 'test'
DEBUG:debug:test
DEBUG:debug:

If you want you can probably avoid this kind of behaviour writing a real write function that calls the_logger.debug only with "full lines".

Anyway I think these kind of solution should only be temporary, and be used only before porting the prints to calls to logging.debug.

(Obviously the loggers should write to a file and not to stdout to avoid the errors.)

这篇关于PyInstaller 打包应用程序在控制台模式下工作正常,在窗口模式下崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆