进程卡在 PyInstaller-executable 循环中 [英] Processes stuck in loop with PyInstaller-executable

查看:33
本文介绍了进程卡在 PyInstaller-executable 循环中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Python v3.5,Windows 10

我正在使用多个进程并尝试捕获用户输入.搜索我看到的所有内容,在多个进程中使用 input() 时会发生奇怪的事情.经过 8 小时以上的尝试,我实施的一切都没有奏效,我很确定我做错了,但我终生无法弄清楚.

以下是一个非常精简的程序,用于演示该问题.现在,当我在 PyCharm 中运行这个程序时它工作正常,但是当我使用 pyinstaller 创建单个可执行文件时它失败了.该程序不断陷入循环,要求用户输入如下所示的内容:.

我很确定这与 Windows 如何从我读过的东西中获取标准输入有关.我也试过将用户输入变量作为 Queue() 项目传递给函数,但同样的问题.我读到你应该把 input() 放在主要的 python 进程中,所以我在 if __name__ = '__main__':

下做了

from multiprocessing import Process导入时间def func_1(duration_1):而持续时间_1 >= 0:时间.sleep(1)打印('Duration_1: %d %s' % (duration_1, 's'))持续时间_1 -= 1def func_2(duration_2):而duration_2 >= 0:时间.sleep(1)打印('Duration_2: %d %s' % (duration_2, 's'))持续时间_2 -= 1如果 __name__ == '__main__':# func_1 用户输入而真:duration_1 = input('请输入一个正整数.')如果duration_1.isdigit():duration_1 = int(duration_1)休息别的:print('**只接受正整数**')继续# func_2 用户输入而真:duration_2 = input('请输入一个正整数.')如果 duration_2.isdigit():duration_2 = int(duration_2)休息别的:print('**只接受正整数**')继续p1 = 进程(目标=func_1,args=(duration_1,))p2 = 进程(目标=func_2,args=(duration_2,))p1.start()p2.start()p1.join()p2.join()

解决方案

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

直接来自文档:

<块引用>

multiprocessing.freeze_support()

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

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

from multiprocessing import Process, freeze_support定义 f():打印('你好世界!')如果 __name__ == '__main__':冻结支持()进程(目标= f).开始()

<块引用>

如果省略 freeze_support() 行,则尝试运行冻结的可执行文件将引发 RuntimeError.

在 Windows 以外的任何操作系统上调用 freeze_support() 都无效.另外,如果模块在Windows上被Python解释器正常运行(程序没有被冻结),那么freeze_support()是没有作用的.

在您的示例中,您还应该解决不必要的代码重复问题.

Python v3.5, Windows 10

I'm using multiple processes and trying to captures user input. Searching everything I see there are odd things that happen when using input() with multiple processes. After 8 hours+ of trying, nothing I implement worked, I'm positive I am doing it wrong but I can't for the life of me figure it out.

The following is a very stripped down program that demonstrates the issue. Now it works fine when I run this program within PyCharm, but when I use pyinstaller to create a single executable it fails. The program constantly is stuck in a loop asking the user to enter something as shown below:.

I am pretty sure it has to do with how Windows takes in standard input from things I've read. I've also tried passing the user input variables as Queue() items to the functions but the same issue. I read you should put input() in the main python process so I did that under 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()

解决方案

You need to use multiprocessing.freeze_support() when you produce a Windows executable with PyInstaller.

Straight out from the docs:

multiprocessing.freeze_support()

Add support for when a program which uses multiprocessing has been frozen to produce a Windows executable. (Has been tested with py2exe, PyInstaller and cx_Freeze.)

One needs to call this function straight after the if name == 'main' line of the main module. For example:

from multiprocessing import Process, freeze_support

def f():
    print('hello world!')

if __name__ == '__main__':
    freeze_support()
    Process(target=f).start()

If the freeze_support() line is omitted then trying to run the frozen executable will raise RuntimeError.

Calling freeze_support() has no effect when invoked on any operating system other than Windows. In addition, if the module is being run normally by the Python interpreter on Windows (the program has not been frozen), then freeze_support() has no effect.

In your example you also have unnecessary code duplication you should tackle.

这篇关于进程卡在 PyInstaller-executable 循环中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆