为什么python.subprocess在proc.communicate()之后挂起?
我有一个叫做为什么python.subprocess在proc.communicate()之后挂起?,python,subprocess,Python,Subprocess,我有一个叫做my_own\u exe的交互式程序。首先,它打印出alive,然后输入S\n,然后再次打印出alive。最后输入L\n。它进行一些处理并退出 然而,当我从下面的python脚本调用它时,程序似乎在打印出第一个“alive”后挂起 这里有人能告诉我为什么会这样吗 //在阅读了后续文章之后(谢谢大家),我修改了代码如下: import subprocess import time base_command = "./AO_FelixStrategy_UnitTest --bats 3
my_own\u exe
的交互式程序。首先,它打印出alive
,然后输入S\n
,然后再次打印出alive
。最后输入L\n
。它进行一些处理并退出
然而,当我从下面的python脚本调用它时,程序似乎在打印出第一个“alive”后挂起
这里有人能告诉我为什么会这样吗
//在阅读了后续文章之后(谢谢大家),我修改了代码如下:
import subprocess
import time
base_command = "./AO_FelixStrategy_UnitTest --bats 31441 --chix 12467 --enxutp 31884 --turq 26372 --symbol SOGN --target_date " + '2009-Oct-16'
print base_command
proc2 = subprocess.Popen(base_command, shell=True , stdin=subprocess.PIPE,)
time.sleep(2);
print "aliv"
proc2.communicate('S\n')
print "alive"
time.sleep(6)
print "alive"
print proc2.communicate('L\n')
time.sleep(6)
程序现在与第一个输入'S\n'配合得很好,但随后停止,第二个'L\n'被忽略了
有人能告诉我为什么会这样吗?来自:
与进程交互:向stdin发送数据。从stdout和stderr读取数据,直到到达文件末尾等待进程终止。
因此,在运行communicate()
之后,进程被终止
如果要在不等待进程停止的情况下写入和读取,请执行以下操作:
- 永远不要使用
——它不需要调用shell来依次调用您的程序,因此在您和您的程序之间会有另一个进程。这有很多令人不快的副作用。默认值是shell=True
,因此您应该坚持使用它。 将您的shell=False
行更改为:Popen
p = subprocess.Popen(["./AO_FelixStrategy_UnitTest", "--bats", "31441", "--chix", "12467", "--enxutp", "31884", "--turq", "26372", "--symbol", "SOGN", "--target_date", '2009-Oct-16'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
- 使用
写入进程。使用p.stdin.write
从中读取p.stdout.read
- 如果没有要读取的内容,则调用
,将阻塞。如果写入缓冲区已满,则调用p.stdout.read
将阻塞。因此,您必须确保您有要读/写的内容—您可以在unix操作系统上使用p.stdin.write
。不幸的是,在windows上,您必须求助于线程。至少这是Popen.Communication内部所做的select
- 如果您没有编写
,则可能存在其他问题:AO_FelixStrategy\u UnitTest
- 它可以从其他地方读取,而不是标准输入。一些程序直接从终端读取,另一些程序使用一些操作系统API读取。这意味着写入stdin的数据不会进入程序。对于密码提示,这通常是正确的
- 请记住,您必须考虑
buffers。默认情况下,标准C管道通信是缓冲的,因此在关闭输入端之前,您可能看不到任何输出(通过执行AO\u FelixStrategy\u UnitTest
。除非p.stdin.close()
定期刷新输出AO\u FelixStrategy\u UnitTest
AO_FelixStrategy\u UnitTest
的开发方式工作:
p = subprocess.Popen(["./AO_FelixStrategy_UnitTest",
"--bats", "31441", "--chix", "12467",
"--enxutp", "31884", "--turq", "26372",
"--symbol", "SOGN", "--target_date", '2009-Oct-16'],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
output = p.communicate('S\nL\n')[0]
print output
communicate()
从stdout和stderr读取数据,直到到达文件末尾。-它将等待程序退出。communicate将只运行一次,然后关闭管道,因此如果要向其发送多个命令,则需要在相同字符串中依次发送
下面是一个经过一些调查后对我有用的示例,尝试了线程、子流程32、stdin.write、stdout.read等。这些信息不在用于通信的官方python参考信息中:
我唯一发现这一点的地方就是这里:
这是代码,很简单,没有线程,没有子进程32,可以在linux和windows上运行。是的,您必须知道向其他进程发送命令的次数,但通常您知道。除此之外,您还可以添加线程、cwd、shell=True或任何其他您可能需要的内容,但这是最简单的情况:
def do_commands(self, cmd, parms):
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE )
# wait for the process to terminate
out, err = process.communicate(cmd_parms)
errcode = process.returncode
return errcode, out, err
例如,如果你想将多个回车(\n)发送给被调用的应用程序,而中间的一个PARAM(交互性地提醒你),你会称它为类似的事情:
cmd_parms = "\n\n\n\n\nparm\n\n"
errcode, out, err = do_commands(command, cmd_parms)
希望能有所帮助。不是每次他调用
proc2
时都会重新启动进程吗?还是因为它前面有两个打印,所以没有调用它?如果是这样,为什么在第一次打印后会冻结而不是第二次打印?@Anthony:不是。进程不会重新启动。在第一次打印后会冻结,因为通信正在等待进程结束,但进程从未结束,因为它可能卡在第二个提示上(应该输入'L\n'
)。谢谢。无论如何,这只能部分解决问题,我只能使用“通信”一次,对吗?如果我需要交互读写和读写,这“output=p.communicate('S\nL\n')[0]”无法工作,对吗?@ccfenix:没错。通过使用.communicate()
,您可以尽快编写这些内容并关闭stdin,并继续收听stdout,直到进程结束。如果您想与进程进行交互对话,您需要按照我所说的使用p.stdin.write
和p.stdout.read
而不是.communicate()
在问题中。我还说明了一些注意事项,比如关于外部可执行文件上可能发生的缓冲的部分。一个更直观的习惯用法是subprocess.Popen(base_command.split()…
那么,与子进程进行来回交互的正确方法是什么?@Anthony:正确的方法是使用p.stdin.write()
和p.stdout.read()
。但是,这些都可以阻止,因此您可以在unix上使用select()
,或在windows上使用线程来避免阻止。请检查.communicate()中的内容
是通过检查您的subprocess.py
源代码来完成的。查看我的答案了解更多详细信息。这不是我的问题,我只是想生成一些可能对修复他的代码有帮助的东西。这一点我真的很好奇,因为我上周末在PHP中做了一些模糊相似的工作,我想知道如何更好-半衰期。