使用 PyInstaller 可执行程序卡在循环中的进程
Posted
技术标签:
【中文标题】使用 PyInstaller 可执行程序卡在循环中的进程【英文标题】:Processes stuck in loop with PyInstaller-executable 【发布时间】:2019-01-06 19:24:02 【问题描述】:Python v3.5,Windows 10
我正在使用多个进程并尝试捕获用户输入。搜索我看到的所有内容时,在将input()
与多个进程一起使用时会发生奇怪的事情。经过 8 小时以上的尝试,我没有实施任何方法,我很肯定我做错了,但我终其一生都无法弄清楚。
以下是演示该问题的非常精简的程序。现在,当我在 PyCharm 中运行这个程序时它可以正常工作,但是当我使用 pyinstaller
创建单个可执行文件时它会失败。程序一直卡在一个循环中,要求用户输入如下所示的内容:。
我很确定这与 Windows 如何从我阅读的内容中获取标准输入有关。我也尝试将用户输入变量作为Queue()
项传递给函数,但同样的问题。我读到您应该将input()
放在主要的python 进程中,所以我在if __name__ = '__main__':
下这样做了
from multiprocessing import Process
import time
def func_1(duration_1):
while duration_1 >= 0:
time.sleep(1)
print('Duration_1: %d %s' % (duration_1, 's'))
duration_1 -= 1
def func_2(duration_2):
while duration_2 >= 0:
time.sleep(1)
print('Duration_2: %d %s' % (duration_2, 's'))
duration_2 -= 1
if __name__ == '__main__':
# func_1 user input
while True:
duration_1 = input('Enter a positive integer.')
if duration_1.isdigit():
duration_1 = int(duration_1)
break
else:
print('**Only positive integers accepted**')
continue
# func_2 user input
while True:
duration_2 = input('Enter a positive integer.')
if duration_2.isdigit():
duration_2 = int(duration_2)
break
else:
print('**Only positive integers accepted**')
continue
p1 = Process(target=func_1, args=(duration_1,))
p2 = Process(target=func_2, args=(duration_2,))
p1.start()
p2.start()
p1.join()
p2.join()
【问题讨论】:
【参考方案1】:当您使用 PyInstaller 生成 Windows 可执行文件时,您需要使用 multiprocessing.freeze_support()
。
直接出docs:
multiprocessing.freeze_support()
添加对使用多处理的程序被冻结以生成 Windows 可执行文件时的支持。 (已使用 py2exe、PyInstaller 和 cx_Freeze 测试。)
需要在主模块的 if name == 'main' 行之后直接调用此函数。例如:
from multiprocessing import Process, freeze_support
def f():
print('hello world!')
if __name__ == '__main__':
freeze_support()
Process(target=f).start()
如果 freeze_support() 行被省略,那么尝试运行冻结的可执行文件将引发 RuntimeError。
在除 Windows 之外的任何操作系统上调用时,调用 freeze_support() 均无效。另外,如果模块在Windows上被Python解释器正常运行(程序没有被冻结),则freeze_support()没有任何作用。
在您的示例中,您还应该解决不必要的代码重复问题。
【讨论】:
什么是重复代码?我想要两个用于用户输入的while循环,因为如果第二个用户输入没有正确输入,我不希望它每次都在开始时重新开始。 @probatfunc1
和 func2
是相同的,您只是使用其他名称,并且可以通过例如为此添加另一个参数来动态更改打印的文本。您也可以将 while 循环放入一个函数中,然后调用两次。
我的真实脚本中的函数中确实有用于用户输入的 while 循环。我只是试着让这个尽可能简单,直接在这里问这个问题。感谢您的帮助,我真的很感激。多处理模块有很多文档,我错过了。以上是关于使用 PyInstaller 可执行程序卡在循环中的进程的主要内容,如果未能解决你的问题,请参考以下文章
如何从我的 kivy 应用程序(Pyinstaller)获取 Windows 可执行文件?
导出单个 .exe 时,PyInstaller 卡在“正在构建 PKG ...”