我试图写一个Python程序,能够与其它程序进行交互。 这意味着发送stdin和接收标准输出数据。 我不能使用Pexpect的(虽然它确实启发了一些设计的)。 我现在使用的过程是这样的:
- 附上PTY的子进程的stdout
- 循环直到通过检查子退出
subprocess.poll
- 当在标准输出可用的数据立即写数据到当前标准输出。
- 完!
我一直在一些原型代码(如下),它的工作原理,但似乎有一个缺陷,是缠着我。 子进程完成后,父进程挂起,如果使用的时候,不指定超时select.select
。 我真的不想设置超时。 它只是似乎有点脏。 然而,似乎所有我试图避开这一问题的其他方法并不管用。 Pexpect的似乎通过绕过它os.execv
和pty.fork
代替subprocess.Popen
和pty.openpty
一个解决方案,我不喜欢。 我做得不对我如何检查是否有子的生活吗? 是我的方法不正确?
我使用的代码如下。 我使用这个在Mac OS X 10.6.8,但我需要它在Ubuntu 12.04正常工作。
这是子亚军runner.py
:
import subprocess
import select
import pty
import os
import sys
def main():
master, slave = pty.openpty()
process = subprocess.Popen(['python', 'outputter.py'],
stdin=subprocess.PIPE,
stdout=slave, stderr=slave, close_fds=True)
while process.poll() is None:
# Just FYI timeout is the last argument to select.select
rlist, wlist, xlist = select.select([master], [], [])
for f in rlist:
output = os.read(f, 1000) # This is used because it doesn't block
sys.stdout.write(output)
sys.stdout.flush()
print "**ALL COMPLETED**"
if __name__ == '__main__':
main()
这是子代码outputter.py
。 奇怪的随机配件只是模拟程序在随机时间间隔输出数据。 如果你愿意,你可以将其删除。 它不应该的问题 :
import time
import sys
import random
def main():
lines = ['hello', 'there', 'what', 'are', 'you', 'doing']
for line in lines:
sys.stdout.write(line + random.choice(['', '\n']))
sys.stdout.flush()
time.sleep(random.choice([1,2,3,4,5])/20.0)
sys.stdout.write("\ndone\n")
sys.stdout.flush()
if __name__ == '__main__':
main()
感谢您的帮助,您都可以提供!
额外注
PTY的使用,因为我想确保stdout不是缓冲。