前面写过两篇相关的文章:
这两篇文章都没有提到下面的这个重要问题:
采用Pyinstaller冻结打包多进程程序时,必须非常小心。这个技术线在Windows上会有一个非常严重的Bug。直接运行打包后的程序会造成无限创建进程,直到系统崩溃。
问题描述
本文针对一个非常具体的场景,需求包括以下要素:
- 需要用PyQt5设计GUI程序
- 需要调用其他库完成后台计算,计算与GUI线程松耦合
- 通过PyInstaller打包成独立可执行程序
多进程的使用
在Python的标准库中,multiprocessing
模块提供了多进程的支持。
如果我们采取这个技术线,则通常采用计算进程的方式来实现。
无限循环的计算进程
def worker(iq, oq):
while True:
# get input from input queue
data = iq.get()
# process data
result = f(data)
# put result to output queue
oq.put(result)
这个是一个典型的单纯的数据处理的计算过程,f(data)
是一个计算函数,iq
是输入队列,oq
是输出队列。这个函数的内部是一个死循环,不断地从输入队列中获取数据,然后处理数据,最后将结果放到输出队列中。函数的大部分时间预计在get()
函数的阻塞(当队列中没有数据时)和f(data)
的计算上。
主进程启动计算进程
import multiprocessing
if __name__ == '__main__':
input_q = multiprocessing.Queue()
output_q = multiprocessing.Queue()
multiprocessing.Process(target=worker,
args=(input_q, output_q),
daemon=True).start()
这里的daemon=True
表示这个进程是一个守护进程,当主进程结束时,这个进程也会结束;否则必须要等待这个进程结束后,才能结束主进程。如果不设置这里或者daemon=False
,就需要在worker
函数中设置一个退出条件。例如:
def worker(iq, oq):
while True:
# get input from input queue
data = iq.get()
if data == 'EXIT':
break
# process data
result = f(data