首页 > 系统相关 >PyQt5 使用 Pyinstaller+multiprocessing 打包多进程应用时,引发的一些问题

PyQt5 使用 Pyinstaller+multiprocessing 打包多进程应用时,引发的一些问题

时间:2024-10-16 12:10:14浏览次数:12  
标签:__ Pyinstaller process self PyQt5 sys 进程 multiprocessing

解决 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_())

运行后,可以得到下面这样的窗口
image

2. 使用下面的两种方式打包

# 方式1,无 -w
pyinstaller -D -y .\test_process.py

# 方式2,有 -w
pyinstaller -D -w -y .\test_process.py

无论那种方式,启动后,若点击“启动后台进程”均无法成功,且主进程会反复启动
image

解决办法

#!/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_())

无论那种打包方式,启动后,均正常运行
image

二、解决AttributeError: 'NoneType' object has no attribute 'write'

这个问题,您不一定有,因为这和你的应用程序有关,上文我们已经通过添加freeze_support()来解决主程序 GUI 反复重启的问题,但是某些时候,当你用pyinstaller -D -w -y .\test_process.py这种无控制台窗口模式(也就是黑窗口)时,就会出现这个问题:
如下图:
image

推测产生的原因

推测产生的原因是因为,使用-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_())

本文章的原文地址
GitHub主页

标签:__,Pyinstaller,process,self,PyQt5,sys,进程,multiprocessing
From: https://www.cnblogs.com/yqbaowo/p/18469347

相关文章

  • PyQt5开发环境搭建和配置
    PyQt5工具可以快速实现简单的界面开发,包括界面设计、布局管理以及业务逻辑实现(信号与槽)。简单说就是使用PyQt5工具可以快速画一个控件摆放整齐、界面整洁有序、布局合理的界面。课程目标可以动手实现简单的GUI程序。系列文章主要以动手实践案例讲解为主。课程对象会一些......
  • 基于YOLO11/v10/v8/v5深度学习的安检X光危险品检测与识别系统设计与实现【python源码+
    《博主简介》小伙伴们好,我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。✌更多学习资源,可关注公-仲-hao:【阿旭算法与机器学习】,共同学习交流~......
  • 如何用PyQt5创建多个窗口,同时获取多个U盘内的文件的名称,并分别在对应窗口打印文件名,要
    在PyQt5中,你可以使用QThread创建多个线程来并行处理每个U盘的文件名获取任务。每个线程负责扫描一个U盘的文件,同时在主窗口显示结果。以下是一个示例代码,用来创建多个窗口,同时在每个窗口中显示各自的U盘文件名:每个窗口使用QWidget。使用QThread创建后台线程获取U......
  • Python 从入门到实战35(进程-multiprocessing模块)
            我们的目标是:通过这一套资料学习下来,可以熟练掌握python基础,然后结合经典实例、实践相结合,使我们完全掌握python,并做到独立完成项目开发的能力。        上篇文章我们讨论了turtle库绘制图画操作的相关知识。今天学习一下进程的概念和创建方法。1、......