我有一个大文件需要在输入另一个命令之前进行处理。我可以将处理后的数据保存为临时文件,但想避免这样做。我编写了一个生成器,它一次处理每一行,然后按照脚本将其作为输入提供给外部命令。但是我在第二轮循环中遇到了“关闭文件上的 I/O 操作”异常:
cmd = ['intersectBed', '-a', 'stdin', '-b', bedfile]
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
for entry in my_entry_generator: # <- this is my generator
output = p.communicate(input='\t'.join(entry) + '\n')[0]
print output
我读到另一个使用 p.stdin.write 的类似问题。但仍然有同样的问题。
我做错了什么?
[编辑]
我用以下内容替换了最后两个语句(感谢 SpliFF):
output = p.communicate(input='\t'.join(entry) + '\n')
if output[1]: print "error:", output[1]
else: print output[0]
查看外部程序是否有任何错误。但不是。
在 p.communicate 线上仍然有相同的异常。
The communicate
的方法subprocess.Popen
对象只能被调用一次。它的作用是将您提供的输入发送给流程while读取所有 stdout 和 stderr 输出。我所说的“全部”是指它等待进程退出,以便知道它拥有所有输出。一次communicate
返回,该进程不再存在。
如果你想使用communicate
,您必须在循环中重新启动该进程,或者为其提供一个字符串all来自生成器的输入。如果你想做流式通信,一点一点地发送数据,那么你就不能使用communicate
。相反,您需要写信给p.stdin
在阅读时p.stdout
and p.stderr
。这样做很棘手,因为您无法判断哪个输出是由哪个输入引起的,而且很容易陷入死锁。有一些第三方库可以帮助您完成此任务,例如 Twisted。
如果你想这样做交互地,发送一些数据,然后等待并处理结果,然后再发送更多数据,事情变得更加困难。您可能应该使用第三方库,例如pexpect
为了那个原因。
当然,如果您可以在循环内启动进程,那就容易多了:
cmd = ['intersectBed', '-a', 'stdin', '-b', bedfile]
for entry in my_entry_generator:
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output = p.communicate(input='\t'.join(entry) + '\n')[0]
print output
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)