如果两个 multiprocessing 可以在终端上请求输入,有没有办法暂停其中一个直到给出答案?

If two multiprocessing can request input on the terminal, is there a way to pause one of them until the answer is given?

从下面的代码中可以看出,两个多处理一起运行,但是两者都有一个时刻可以在终端中请求一个input(),有什么办法可以暂停另一个多处理直到得到答案在终端中给出?

文件Code_One 加速解释的古老而简单的例子:

from time import sleep

def main():
        sleep(1)
        print('run')
        sleep(1)
        print('run')
        sleep(1)
        input('Please, give the number:')

文件Code_Two 加速解释的古老而简单的例子:

from time import sleep

def main():
        sleep(2)
        input('Please, give the number:')
        sleep(1)
        print('run 2')
        sleep(1)
        print('run 2')
        sleep(1)
        print('run 2')
        sleep(1)
        print('run 2')
        sleep(1)
        print('run 2')

文件Main_Code:

import Code_One
import Code_Two
import multiprocessing
from time import sleep

def main():
    while True:
        pression = multiprocessing.Process(target=Code_One.main)
        xgoals = multiprocessing.Process(target=Code_Two.main)
        pression.start()
        xgoals.start()
        pression.join()
        xgoals.join()
        print('Done')
        sleep(5)

if __name__ == '__main__':
    main()

遇到这种情况我该如何处理?

在这个例子中,因为它不会暂停另一个 multi,每当它要求输入时就会发生这个错误:

input('Please, give the number:')
EOFError: EOF when reading a line

当然,这是可能的。为此,您需要使用某种进程间通信 (IPC) 机制来允许两个进程进行协调。 time.sleep 虽然不是最佳选择,但有更有效的方法可以解决这个问题。

可能最有效的方法是使用 multiprocessing.Event,像这样:

import multiprocessing
import sys
import os

def Code_One(event, fno):
    proc_name = multiprocessing.current_process().name
    print(f'running {proc_name}')
    sys.stdin = os.fdopen(fno)
    val = input('give proc 1 input: ')
    print(f'proc 1 got input: {val}')
    event.set()


def Code_Two(event, fno):
    proc_name = multiprocessing.current_process().name
    print(f'running {proc_name} and waiting...')
    event.wait()
    sys.stdin = os.fdopen(fno)
    val = input('give proc 2 input: ')
    print(f'proc 2 got input {val}')


if __name__ == '__main__':
    event = multiprocessing.Event()
    pression = multiprocessing.Process(name='code_one', target=Code_One, args=(event, sys.stdin.fileno()))
    xgoals = multiprocessing.Process(name='code_two', target=Code_Two, args=(event, sys.stdin.fileno()))
    xgoals.start()
    pression.start()
    xgoals.join()
    pression.join()

这将创建 event object 和两个子进程。事件 object 有一个内部标志,从 False 开始,然后可以通过调用 event.set() 的任何进程切换 True。如果一个进程在标志为 False 时调用 event.wait(),则该进程将阻塞,直到另一个进程调用 event.set().

event在parent进程中创建,并作为参数传递给每个子进程。 Code_Two 开始并调用 event.wait(),它会阻塞直到 event 中的内部标志设置为 TrueCode_One 立即执行,然后调用 event.set(),它将 event 的内部标志设置为 True,并允许 Code_Two 继续。此时两个进程都已返回并调用 join,程序结束。

这有点老套,因为它还将 stdin 文件编号从 parent 传递到 child 进程。这是必要的,因为当子进程被分叉时,那些文件描述符被关闭,所以对于 child 进程使用 input 读取 stdin 它首先需要打开正确的输入流(这就是sys.stdin = os.fdopen(fno) 正在做)。将 sys.stdin 作为另一个参数发送到 child 是行不通的,因为 Python 用于为分叉进程设置环境的机制(sys.stdin 是一个 IO 包装器 object 并且不可腌制)。