解决 Pyinstaller 打包 PyQt5+multiprocessing 多进程应用时,引发的一些问题,包括反复启动主进程,以及:AttributeError: 'NoneType' object has no attribute 'write'
本文提供一些解决方案,您可能需要根据自己的实际情况,逐个尝试,直到自己的multiprocessing
多进程应用正常运行
一、解决反复启动 GUI 主进程的问题
这个问题的产生原因,只知道是与Windows
系统有关,因为Python
官方在multiprocessing
库中指明,这个方法只影响windows
系统,且主要针对生成可执行文件,也就是Windows
下的 exe
程序
官方原文:multiprocessing.freeze_support()
问题复现
1. 准备示例程序
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
"""
@ File : test_multiprocessing.py
@ Author : yqbao
@ Version : V1.0.0
@ Description :
"""
import sys
from multiprocessing import Process
import time
from PyQt5.QtWidgets import QApplication, QPushButton, QVBoxLayout, QWidget
def background_task():
while True:
print("后台进程正在运行...")
time.sleep(3) # 模拟一些后台工作
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setWindowTitle('PyQt5 与 Multiprocessing')
layout = QVBoxLayout()
self.start_button = QPushButton('启动后台进程')
self.start_button.clicked.connect(self.start_process)
layout.addWidget(self.start_button)
self.setLayout(layout)
def start_process(self):
self.process = Process(target=background_task)
self.process.start()
print("后台进程已启动。")
def closeEvent(self, event):
self.process.terminate()
self.process.join()
event.accept()
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
运行后,可以得到下面这样的窗口
2. 使用下面的两种方式打包
# 方式1,无 -w
pyinstaller -D -y .\test_process.py
# 方式2,有 -w
pyinstaller -D -w -y .\test_process.py
无论那种方式,启动后,若点击“启动后台进程”均无法成功,且主进程会反复启动
解决办法
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
"""
@ File : test_multiprocessing.py
@ Author : yqbao
@ Version : V1.0.0
@ Description :
"""
from multiprocessing import freeze_support
... # 忽略,无变化
if __name__ == '__main__':
freeze_support() # 使用冻结
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
无论那种打包方式,启动后,均正常运行
二、解决AttributeError: 'NoneType' object has no attribute 'write'
这个问题,您不一定有,因为这和你的应用程序有关,上文我们已经通过添加freeze_support()
来解决主程序 GUI 反复重启的问题,但是某些时候,当你用pyinstaller -D -w -y .\test_process.py
这种无控制台窗口模式(也就是黑窗口)时,就会出现这个问题:
如下图:
推测产生的原因
推测产生的原因是因为,使用-w
无控制台窗口模式时,标准输出被重定向了,导致相关函数无法得到正确初始化,于是反应出来就是NoneType
解决办法
方法1:尝试使用--noconsole
代替 --windowed(-w)
此参数是完全禁用控制台窗口,而不是重定向
方法2:手动重定向输出
```python
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
"""
@ Author : yqbao
@ Version : V1.0.0
@ Description :
"""
... # 忽略,您自己的应用程序
if __name__ == "__main__":
sys.stdout = open('output.txt', 'w') # 手动重定向
sys.stderr = open('error.txt', 'w') # 手动重定向
freeze_support()
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
标签:__,Pyinstaller,process,self,PyQt5,sys,进程,multiprocessing
From: https://www.cnblogs.com/yqbaowo/p/18469347