【问题标题】:Processes stuck in loop with PyInstaller-executable使用 PyInstaller 可执行程序卡在循环中的进程
【发布时间】:2021-03-01 23:32:51
【问题描述】:

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()

【问题讨论】:

    标签: python windows parallel-processing pyinstaller python-multiprocessing


    【解决方案1】:

    当您使用 PyInstaller 生成 Windows 可执行文件时,您需要使用 multiprocessing.freeze_support()

    直接出docs

    multiprocessing.freeze_support()

    添加对使用多处理的程序被冻结以生成 Windows 可执行文件时的支持。 (已使用 py2exe、PyInstaller 和 cx_Freeze 测试。)

    需要在主模块的 if name == 'ma​​in' 行之后直接调用此函数。例如:

    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循环,因为如果第二个用户输入没有正确输入,我不希望它每次都在开始时重新开始。
    • @probat func1func2 是相同的,您只是使用其他名称,并且可以通过例如为此添加另一个参数来动态更改打印的文本。您也可以将 while 循环放入一个函数中,然后调用两次。
    • 我的真实脚本中的函数中确实有用于用户输入的 while 循环。我只是试着让这个尽可能简单,直接在这里问这个问题。感谢您的帮助,我真的很感激。多处理模块有很多文档,我错过了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-13
    • 1970-01-01
    • 1970-01-01
    • 2011-05-22
    • 1970-01-01
    相关资源
    最近更新 更多