首页 > 解决方案 > Python input() 阻止子进程执行

问题描述

我有一个接受用户输入的 Python 脚本。不同的用户输入触发不同的功能。这里讨论的功能是产生多个进程的功能。这是脚本,main.py.

import time
import threading
import concurrent.futures as cf


def executeparallelprocesses():

    numprocesses = 2
    durationseconds = 10

    futures = []

    print('Submit jobs as new processes.')
    with cf.ProcessPoolExecutor(max_workers=numprocesses) as executor:
        for i in range(numprocesses):
            futures.append(executor.submit(workcpu, 500, durationseconds))
            print('job submitted')
        print('all jobs submitted')

        print('Wait for jobs to complete.', flush=True)
        for future in cf.as_completed(futures):
            future.result()

        print('All jobs done.', flush=True)


def workcpu(x, durationseconds):
    print('Job executing in new process.')
    start = time.time()
    while time.time() - start < durationseconds:
        x * x


def main():

    while True:
        cmd = input('Press ENTER\n')
        if cmd == 'q':
            break
        thread = threading.Thread(target=executeparallelprocesses)
        thread.start()

    time.sleep(15)


if __name__ == '__main__':
    main()

当从终端调用此脚本时,它按预期工作(即,子流程执行)。具体来说,请注意两行“作业在新进程中执行”。在下面的示例运行中:

(terminal prompt $) python3 main.py
Press ENTER

Submit jobs as new processes.
Press ENTER
job submitted
job submitted
all jobs submitted
Wait for jobs to complete.
Job executing in new process.
Job executing in new process.
All jobs done.
q
(terminal prompt $)

问题: 当从另一个程序调用脚本时,子进程不会被执行。这是驱动程序脚本driver.py

import time
import subprocess
from subprocess import PIPE


args = ['python3', 'main.py']

p = subprocess.Popen(args, bufsize=0, stdin=PIPE, universal_newlines=True)

time.sleep(1)

print('', file=p.stdin, flush=True)

time.sleep(1)

print('q', file=p.stdin, flush=True)

time.sleep(20)

注意“作业在新进程中执行”的方式。以下示例运行的输出中不存在:

(terminal prompt $) python3 driver.py
Press ENTER
Submit jobs as new processes.
Press ENTER
job submitted
job submitted
all jobs submitted
Wait for jobs to complete.
(terminal prompt $)

似乎 in 中的cmd = input('Press ENTER\n')语句main.py正在阻塞并阻止子进程执行。奇怪的是,注释掉第二条time.sleep(1)语句driver.py会导致main.py子进程按预期生成。使这个“工作”的另一种方法是time.sleep(1)在 的循环中添加main.py, 之后thread.start().

这种对时间敏感的代码很脆弱。有没有一种强大的方法来做到这一点?

标签: pythonpython-3.xcommand-line-interfacepython-multithreadingconcurrent.futures

解决方案


我尝试了 ShadowRanger 的建议来添加对multiprocessing.set_start_method()

if __name__ == '__main__':
    multiprocessing.set_start_method('spawn')
    main()

这为我解决了这个问题。我将阅读文档以了解更多信息。


推荐阅读