通过STDIN/STDOUT使用Python启动和控制外部进程
我需要启动一个外部程序,并通过发送和接收信息来控制它,这些信息通过标准输入(stdin)和标准输出(stdout)进行交流。使用subprocess.Popen我可以启动这个程序,但我无法通过stdin来控制它的执行,这正是我需要的。
我想完成的流程是:
- 启动外部程序
- 进行若干步骤的循环
- 通过向它的stdin写入换行符,告诉外部程序完成下一步处理
- 等待外部程序通过向它的stdout写入换行符来表示它已经完成了这一步
- 关闭外部程序的stdin,以表示执行已经完成。
到目前为止,我想出了以下内容:
process = subprocess.Popen([PathToProcess], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
for i in xrange(StepsToComplete):
print "Forcing step # %s" % i
process.communicate(input='\n')
当我运行上面的代码时,换行符('\n')没有传递给外部程序,我一直停留在第0步。代码在process.communicate()这里卡住了,无法继续。我是不是错误地使用了communicate()方法?
另外,我该如何实现“等待外部程序写入换行符”的功能呢?
2 个回答
0
你可以使用Twisted这个库,通过调用reactor.spawnProcess和LineReceiver来实现。
9
使用 process.communicate(input='\n') 是不对的。如果你查看 Python 的文档,你会发现它是把你的字符串写入子进程的标准输入(stdin),然后读取子进程的所有输出,直到子进程结束。从 doc.python.org 的描述来看:
Popen.communicate(input=None) 与进程交互:发送数据到标准输入。读取标准输出和标准错误,直到文件结束。等待进程终止。可选的输入参数应该是一个要发送给子进程的字符串,或者是 None,如果不需要发送数据给子进程的话。
实际上,你应该只向子进程的标准输入写入数据。然后在你的循环中读取它。
更像是这样:
process=subprocess.Popen([PathToProcess],stdin=subprocess.PIPE,stdout=subprocess.PIPE);
for i in xrange(StepsToComplete):
print "Forcing step # %s"%i
process.stdin.write("\n")
result=process.stdout.readline()
这样做的效果更接近你想要的。