python,subprocess:从子进程读取输出
我有以下这个脚本:
#!/usr/bin/python
while True:
x = raw_input()
print x[::-1]
我是在 ipython
中调用它的:
In [5]: p = Popen('./script.py', stdin=PIPE)
In [6]: p.stdin.write('abc\n')
cba
而且它运行得很好。
但是,当我这样做的时候:
In [7]: p = Popen('./script.py', stdin=PIPE, stdout=PIPE)
In [8]: p.stdin.write('abc\n')
In [9]: p.stdout.read()
解释器就卡住了。我到底做错了什么?我希望能够多次从另一个进程中写入和读取,以便把一些任务传递给这个进程。我需要做些什么不同的事情呢?
编辑 1
如果我使用 communicate
,我得到的是:
In [7]: p = Popen('./script.py', stdin=PIPE, stdout=PIPE)
In [8]: p.communicate('abc\n')
Traceback (most recent call last):
File "./script.py", line 4, in <module>
x = raw_input()
EOFError: EOF when reading a line
Out[8]: ('cba\n', None)
编辑 2
我尝试了刷新:
#!/usr/bin/python
import sys
while True:
x = raw_input()
print x[::-1]
sys.stdout.flush()
还有这里:
In [5]: from subprocess import PIPE, Popen
In [6]: p = Popen('./script.py', stdin=PIPE, stdout=PIPE)
In [7]: p.stdin.write('abc')
In [8]: p.stdin.flush()
In [9]: p.stdout.read()
但它又卡住了。
6 个回答
3
如果你想把多行内容传给 script.py
,那么你需要同时进行读和写:
#!/usr/bin/env python
import sys
from subprocess import PIPE, Popen
from threading import Thread
def print_output(out, ntrim=80):
for line in out:
print len(line)
if len(line) > ntrim: # truncate long output
line = line[:ntrim-2]+'..'
print line.rstrip()
if __name__=="__main__":
p = Popen(['python', 'script.py'], stdin=PIPE, stdout=PIPE)
Thread(target=print_output, args=(p.stdout,)).start()
for s in ['abc', 'def', 'ab'*10**7, 'ghi']:
print >>p.stdin, s
p.stdin.close()
sys.exit(p.wait()) #NOTE: read http://docs.python.org/library/subprocess.html#subprocess.Popen.wait
输出结果:
4 cba 4 fed 20000001 bababababababababababababababababababababababababababababababababababababababa.. 4 ihg
这里是 script.py
的内容:
#!/usr/bin/env python
"""Print reverse lines."""
while True:
try: x = raw_input()
except EOFError:
break # no more input
else:
print x[::-1]
或者
#!/usr/bin/env python
"""Print reverse lines."""
import sys
for line in sys.stdin:
print line.rstrip()[::-1]
或者
#!/usr/bin/env python
"""Print reverse lines."""
import fileinput
for line in fileinput.input(): # accept files specified as command line arguments
print line.rstrip()[::-1]
3
subprocess模块中的方法 check_output 对这个问题很有帮助:
output = subprocess.check_output('./script.py')
这里的output就是运行这个脚本时的标准输出内容。如果你还需要错误输出的话:
output = subprocess.check_output('./script.py', stderr=subprocess.STDOUT)
因为你不需要直接处理管道,这样可能就能解决你的问题。
15
我觉得这里有两个问题:
1) 你的父脚本调用了 p.stdout.read()
,这个命令会一直读取数据,直到文件结束。但是你的子脚本是一个无限循环,所以文件永远不会结束。你可能想用 p.stdout.readline()
,这样可以逐行读取。
2) 在交互模式下,大多数程序一次只处理一行数据。当从其他程序运行时,它们会处理更多的数据。这样做在很多情况下提高了效率,但当两个程序需要互动时,就会出现问题。
在 p.stdin.write('abc\n')
之后,添加:
p.stdin.flush()
在你的子进程脚本中,在 print x[::-1]
之后,在循环内添加以下内容:
sys.stdout.flush()
(并在最上面添加 import sys
)