Apo*_*tus 4 python subprocess stdout
我想重复发送处理标准输入的请求,并从标准输出接收响应,而不需要subprocess多次调用.我可以实现一次性请求 - 响应迭代,p.communicate但不要调用subprocess我需要使用的多次:process.stdout.readline()挂起.如何正确使用?我使用Python 2.7 64位,Windows 7.在此先感谢.
main.py:
import subprocess
p = subprocess.Popen(['python','subproc.py'],stdin=subprocess.PIPE,stdout=subprocess.PIPE)
while True:
s=raw_input('Enter message:')
p.stdin.write(s)
p.stdin.flush()
response = p.stdout.readline()
if response!= '':
print "Process response:", response
else:
break
Run Code Online (Sandbox Code Playgroud)
subproc.py:
from __future__ import division
import pyximport
s=raw_input()
print 'Input=',s
Run Code Online (Sandbox Code Playgroud)
为了实现这一目标,您可以进行一些小的调整.首先是使用该-u选项禁用子缓冲输出.第二种是将换行符与用户输入的消息一起发送到子进程,以便子进程中的raw_input呼叫完成.
main.py
import subprocess
# We use the -u option to tell Python to use unbuffered output
p = subprocess.Popen(['python','-u', 'subproc.py'],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
while True:
s = raw_input('Enter message:')
p.stdin.write(s + "\n") # Include '\n'
p.stdin.flush()
response = p.stdout.readline()
if response != '':
print "Process response:", response
else:
break
Run Code Online (Sandbox Code Playgroud)
您还应该将子进程包装在无限循环中,否则在发送第一条消息后会出现问题:
subproc.py:
while True:
s = raw_input()
print 'Input=',s
Run Code Online (Sandbox Code Playgroud)
输出:
dan@dantop:~$ ./main.py
Enter message:asdf
Process response: Input= asdf
Enter message:asdf
Process response: Input= asdf
Enter message:blah blah
Process response: Input= blah blah
Enter message:ok
Process response: Input= ok
Run Code Online (Sandbox Code Playgroud)
假设子进程将立即获取您发送到其标准输入的完整数据是不安全的,因为缓冲区可能会妨碍。如果您必须保持文件打开以进行进一步输出,那么您至少应该调用它的flush()方法。
此外,假设子进程的输出将立即可供您阅读也是不安全的。如果它不刷新(或关闭)其输出流,则 EOL 可能会被缓冲,如果您不采取任何措施提示子进程进一步采取行动,那么您readline()可能会永远等待。但是你的程序就不能做任何事情,因为它被困在readline(). 如果子进程是为此构建的,那么您可能会使其正常工作,但否则您需要使用更安全的方法,例如subprocess.communicate().
communicate()正如您所观察到的,在同一个子进程上调用多次是行不通的。正如您从其文档中所期望的那样:它读取所有输出直到文件末尾,并等待子进程终止。要在此模式下发送多个输入,请构建一个包含所有输入的字符串,将其传递给communicate()然后读取所有答案。
或者,如果您确实需要在写入和读取之间交替,并且您的子进程没有专门为此设计的工具,那么在单独的线程中进行读取和写入会更安全,而不需要假设写入和读取完美地交错。
小智 -5
您需要用于communicate与子流程交互(https://docs.python.org/2/library/subprocess.html#subprocess.Popen.communicate)。这是主要代码的更新版本:
import subprocess
p = subprocess.Popen(['python','subproc.py'],stdin=subprocess.PIPE,stdout=subprocess.PIPE)
while True:
s = raw_input('Enter message:')
response, _ = p.communicate(s)
if response!= '':
print "Process response:", response
else:
break
Run Code Online (Sandbox Code Playgroud)
您还必须小心,当主代码中有循环时,您的子过程代码仅运行一次。只有第一次迭代才能正确接收响应,第二次communicate调用将引发异常,因为stdin届时子流程的文件将被关闭。
| 归档时间: |
|
| 查看次数: |
7070 次 |
| 最近记录: |