Python input()阻止子进程执行

问题描述 投票:0回答:2

我有一个接受用户输入的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 $)

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

此时间敏感代码易碎。有没有健壮的方法可以做到这一点?

python python-3.x command-line-interface python-multithreading concurrent.futures
2个回答
0
投票

问题在于您如何尝试使用stdin=PIPE与第二个脚本进行通信-尝试对第二个脚本进行以下操作:

import time
import subprocess
from subprocess import PIPE


args = ['python', 'junk.py']

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

p.communicate(input='\nq\n')

time.sleep(20)

输出:

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.

Process finished with exit code 0

请注意,您可能应该考虑加入已完成的流程,而不是在所有位置插入超时,但这超出了问题。


0
投票

我尝试了ShadowRanger的建议,将呼叫添加到multiprocessing.set_start_method()

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

这为我解决了问题。我将阅读documentation以了解有关此内容的更多信息。

© www.soinside.com 2019 - 2024. All rights reserved.