在Python进程中读取stdin?

在Python进程中读取stdin?,python,process,stdin,Python,Process,Stdin,我试图从Python进程对象内部读取sys.stdin,但我一直得到一个“ValueError:I/O operation on closed file”结果。下面是一个简单的例子: import sys from multiprocessing import Process def do_something(input_data): for x in input_data: print x input=sys.stdin p = Process(target=d

我试图从Python进程对象内部读取sys.stdin,但我一直得到一个“ValueError:I/O operation on closed file”结果。下面是一个简单的例子:

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\u something(input)
就可以了,无需使用进程。创建一个
Pipe()
对象似乎很有帮助——我可以将stdin的内容写入管道,并从流程中以字符串形式获得结果——但实际上,我需要输入类似于文件的表单,以便进行一些下游操作。我可以将内容转储到一个文件中,然后从进程中重新读取它,但这看起来相当笨拙,特别是如果stdin非常大的话。是否有一些简单的方法可以从进程中读取sys.stdin

您必须在某个时刻关闭您试图写入的文件。检查您的代码并尝试删除所有关闭文件的行(fileVariableName.close()),然后查看它是否有效。如果确实如此,则逐个重新添加以查找问题。一旦你找到了引起问题的那一行,试着把它移到程序中(稍后再调用),看看这是否能解决你的问题

编辑:更改

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


并去掉
input=sys.stdin
这是因为在进程开始之前,
stdin
是关闭的。否则,父进程和子进程(或多个子进程)都可能尝试从同一个stdin读取数据,这是一个坏主意

在子进程中,
sys.stdin
实际上被重定向到
/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()
应打印类似于以下内容的内容:

(,)
(, 3)
这里传递的参数是对封闭文件对象的引用,尝试使用它将引发您看到的错误

您可以通过在父级中使用on
sys.stdin.fileno()
来解决这个问题,并将返回的文件描述符副本作为参数传递给子级,然后在子级中使用它


更干净的解决方案可能是读取父进程中的输入并使用。

我发布的示例代码演示了这个问题,但它不包括任何显式的文件关闭,所以我很确定这不是问题所在。还要记住,“文件”是sys.stdin,不是一个常规文件。请尝试将
input=sys.stdin
更改为
input=sys.stdin.readlines()
,这会有所帮助,但它会在继续之前将所有stdin读入内存,这是我希望避免的行为。输入可能非常大,在开始处理之前我不想全部读取。现在发生的是,您正在使输入等于
sys.stdin
本身,而不是其中的值(有点像文件)但是,当您稍后在函数中调用它时,由于某些原因它没有打开,为什么不尝试快速更改呢。我将编辑我的答案,因为这里没有足够的空间。
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()