我试图从Python Process对象内部读取sys.stdin,但我一直在关闭文件中获得" ValueError:I / O操作"结果。这是一个简单的例子:
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中读取?
答案 0 :(得分:2)
这是因为在启动流程之前,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()
应该打印类似的东西:
(<closed file '<stdin>', mode 'r' at 0x7f3b4564b0c0>,)
(<open file '/dev/null', mode 'r' at 0x7f3b43a9e0c0>, 3)
这里传递的参数是对已关闭文件对象的引用,尝试使用它会引发您看到的错误。
您可以通过在父级sys.stdin.fileno()
上使用os.dup()
来解决此问题,并将返回的文件描述符副本作为参数传递给子级,然后您可以使用os.fdopen()
来与之合作。
更干净的解决方案可能是使用pass it to the child读取父进程中的输入和multiprocessing.Queue
。
答案 1 :(得分:0)
您必须在某个时候关闭您尝试写入的文件。检查您的代码并尝试删除所有关闭文件的行( fileVariableName .close())并查看它是否有效。如果是,则逐个重新添加它们以找到问题。一旦找到导致问题的行,请尝试将其进一步移入程序(稍后调用),看看是否能解决问题。
编辑:更改
def do_something(input_data):
for x in input_data:
print x
到
def do_something():
for x in sys.stdin:
print x
并摆脱input = sys.stdin