Python 多处理标准输入

Python multiprocessing stdin input

所有代码在 python 3.4 windows 7.

上编写和测试

我正在设计一个控制台应用程序,需要从命令行 (win os) 使用标准输入来发出命令并更改程序的运行模式。该程序依赖多处理来处理 cpu 绑定负载以传播到多个处理器。

我正在使用 stdout 监控该状态和一些基本 return 信息,并使用 stdin 发出命令以根据 returned 控制台信息加载不同的子进程。

这是我发现问题的地方。我无法让多处理模块接受 stdin 输入,但 stdout 工作正常。我认为在 stack 上找到了以下帮助所以我测试了它并发现使用线程模块这一切都很好,除了所有到 stdout 的输出都暂停,直到每次循环 stdin 由于 GIL 锁定标准输入阻塞。

我会说我已经成功地解决了 msvcrt.kbhit() 的问题。但是,我不禁想知道多处理功能中是否存在某种错误,导致标准输入无法读取任何数据。我尝试了多种方法,但在使用多处理时没有任何效果。甚至尝试使用队列,但我没有尝试使用池或多处理中的任何其他方法。

我也没有在我的 linux 机器上尝试这个,因为我正专注于让它工作。

这是未按预期运行的简化测试代码(提醒这是在 Python 3.4 - win7 中编写的):

import sys
import time
from multiprocessing import Process

def function1():
    while True:
        print("Function 1")
        time.sleep(1.33)

def function2():
    while True:
        print("Function 2")
        c = sys.stdin.read(1) # Does not appear to be waiting for read before continuing loop.
        sys.stdout.write(c) #nothing  in 'c'
        sys.stdout.write(".") #checking to see if it works at all.
        print(str(c)) #trying something else, still nothing in 'c'
        time.sleep(1.66)

if __name__ == "__main__":
    p1 = Process(target=function1)
    p2 = Process(target=function2)
    p1.start()
    p2.start()

希望有人能阐明这是否是预期的功能,如果我没有正确实现它,或者其他一些有用的信息。

谢谢。

当您查看 multiprocessing.Process._bootstrap() 的 Python 实现时,您会看到:

if sys.stdin is not None:
    try:
        sys.stdin.close()
        sys.stdin = open(os.devnull)
    except (OSError, ValueError):
        pass

您也可以通过以下方式确认:

>>> import sys
>>> import multiprocessing
>>> def func():
...     print(sys.stdin)
... 
>>> p = multiprocessing.Process(target=func)
>>> p.start()
>>> <_io.TextIOWrapper name='/dev/null' mode='r' encoding='UTF-8'>

并立即从 os.devnull 读取 returns 空结果:

>>> import os
>>> f = open(os.devnull)
>>> f.read(1)
''

您可以使用 open(0):

来解决这个问题

file is either a string or bytes object giving the pathname (absolute or relative to the current working directory) of the file to be opened or an integer file descriptor of the file to be wrapped. (If a file descriptor is given, it is closed when the returned I/O object is closed, unless closefd is set to False.)

"0 file descriptor"

File descriptors are small integers corresponding to a file that has been opened by the current process. For example, standard input is usually file descriptor 0, standard output is 1, and standard error is 2:

>>> def func():
...     sys.stdin = open(0)
...     print(sys.stdin)
...     c = sys.stdin.read(1)
...     print('Got', c)
... 
>>> multiprocessing.Process(target=func).start()
>>> <_io.TextIOWrapper name=0 mode='r' encoding='UTF-8'>
Got a