使用子进程与程序反复交互

0 投票
2 回答
1014 浏览
提问于 2025-04-18 06:37

我正在尝试运行一个需要连续互动的程序(我需要用字符串'0'或'1'来回答)。

我的代码:

from subprocess import Popen, PIPE

command = ['program', '-arg1', 'path/file_to_arg1']

p = Popen(command, stdin=PIPE, stdout=PIPE)
p.communicate('0'.encode())

最后两行代码在第一次互动时能正常工作,但之后程序会把所有后续的问题都打印出来,而不等我输入答案。其实我需要的是先回答第一个问题,等程序处理完这个问题并打印出第二个问题后,再回答第二个问题,依此类推。

有没有什么好的建议?谢谢!

PS:我使用的是Python 3.3.4

2 个回答

0

如果你想要实时捕捉子进程的标准输出,可以看看这个讨论帖:实时捕捉子进程的标准输出

1

subprocess模块是为了单次交互而设计的。也就是说,你可以向一个进程发送信息,然后读取结果,之后就结束了。要实现与Unix进程之间持续的来回互动,比如不断地读写信息,这就比较困难。我建议使用专门为这个任务设计的库,而不是从头开始重新编写所有必要的逻辑。

有一个经典的库叫做 Expect,它在与子进程交互时表现得很好。还有一个Python实现版本叫做 Pexpect(你可以在 这里 阅读文档)。我推荐使用Pexpect或者类似的库。

Pexpect的工作原理是这样的:

# spawn a subprocess.
# then wait for expected output from the child process,
# and send additional commands to the child.

child = pexpect.spawnu('ftp ftp.openbsd.org')
child.expect('(?i)name .*: ')
child.sendline('anonymous')
child.expect('(?i)password')
child.sendline('pexpect@sourceforge.net')
child.expect('ftp> ')
child.sendline('cd /pub/OpenBSD/3.7/packages/i386')
child.expect('ftp> ')

撰写回答