从 Python 进程中的 stdin 读取? [英] Read from stdin in Python Process?

查看:52
本文介绍了从 Python 进程中的 stdin 读取?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从 Python Process 对象内部读取 sys.stdin,但我不断收到ValueError: I/O operation on closed file"结果.这是一个简单的例子:

I'm trying to read from sys.stdin from inside of a Python Process object, but I keep getting a "ValueError: I/O operation on closed file" result. Here's a quick example:

import sys
from multiprocessing import Process

def do_something(input_data):
    for x in input_data:
        print x


input=sys.stdin

p = Process(target=do_something, args=(input,))
p.start() 
p.join() #Wait for Process to complete 

上述脚本总是失败:

Traceback (most recent call last):
  File "/usr/local/Cellar/python/2.7.5/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/process.py", line 258, in _bootstrap
    self.run()
  File "/usr/local/Cellar/python/2.7.5/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/process.py", line 114, in run
    self._target(*self._args, **self._kwargs)
  File "example.py", line 6, in do_something
    for x in input_data:
ValueError: I/O operation on closed file

当然,只需调用 do_something(input) 就可以在不使用进程的情况下正常工作.创建一个 Pipe() 对象似乎有帮助 - 我可以将 stdin 的内容写入 Pipe 并从进程内以字符串形式获取结果 - 但我实际上需要输入到类似文件的形式对于一些下游操作.我可以将内容转储到一个文件中,然后从 Process 中重新读取它,但这似乎很笨拙,尤其是在 stdin 非常大的情况下.是否有一些简单的方法可以从进程中读取 sys.stdin?

Just calling do_something(input) works fine without using a Process, of course. Creating a Pipe() object seems to help - I can write the contents of stdin to the Pipe and get the results in string form from within the process - but I actually need the input to file-like form for some downstream operations. I could dump the contents to a file and the re-read it in from within the Process, but that seems pretty clumsy, especially if the stdin is really big. Is there some easy way to read from sys.stdin from within a Process?

推荐答案

这是因为在 Process 启动之前,stdin 是关闭的.否则可能会发生父进程和子进程(或多个子进程)都试图从同一个标准输入读取数据,这是一个坏主意.

This is because before the Process is started, stdin is closed. Otherwise it could happen that both the parent and child process (or multiple child processes) try to read from the same stdin, which is a bad idea.

在子进程中sys.stdin实际上是重定向到/dev/null:

In the child process sys.stdin is actually redirected to /dev/null:

from multiprocessing import Process
import sys

def test(*args):
    print(args)
    print(sys.stdin, sys.stdin.fileno())

if __name__ == '__main__':
    p = Process(target=test, args=(sys.stdin,))
    p.start()
    p.join()

应该打印类似这样的东西:

should print something similar to this:

(<closed file '<stdin>', mode 'r' at 0x7f3b4564b0c0>,)
(<open file '/dev/null', mode 'r' at 0x7f3b43a9e0c0>, 3)

此处传递的参数是对关闭文件对象的引用,尝试使用它会引发您所看到的错误.

The passed argument here is a reference to a closed file object, trying to use it will raise the error you've seen.

您可以使用 os.dup() 在父级中的 sys.stdin.fileno() 上,并将返回的文件描述符副本作为参数传递给子级,然后您可以使用 os.fdopen() 使用它.

You could get around this by using os.dup() on sys.stdin.fileno() in the parent and pass the returned copy of the file descriptor to the child as argument, where you can then use os.fdopen() to work with it.

更简洁的解决方案可能是读取父进程中的输入和 使用<将其传递给孩子代码>multiprocessing.Queue.

The cleaner solution would probably be to read the input in the parent process and pass it to the child using a multiprocessing.Queue.

这篇关于从 Python 进程中的 stdin 读取?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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