[英]why does python.subprocess hang after proc.communicate()?
I've got an interactive program called my_own_exe
.我有一个名为
my_own_exe
的交互式程序。 First, it prints out alive
, then you input S\\n
and then it prints out alive
again.首先,它打印出
alive
,然后你输入S\\n
然后它再次打印出alive
。 Finally you input L\\n
.最后你输入
L\\n
。 It does some processing and exits.它进行一些处理并退出。
However, when I call it from the following python script, the program seemed to hang after printing out the first 'alive'.但是,当我从以下 python 脚本调用它时,该程序似乎在打印出第一个 'alive' 后挂起。
Can anyone here tell me why this is happening?这里有人能告诉我为什么会这样吗?
// after reading the follow ups (thank you guys), i modified the code as following: // 阅读完后续(谢谢大家)后,我修改了代码如下:
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)
the program now goes well with the first input 'S\\n', but then stopped, and I the second 'L\\n' is kinda ignored.该程序现在与第一个输入 'S\\n' 运行良好,但随后停止,而第二个 'L\\n' 有点被忽略。
Can anyone give me an idea why it's like this?谁能告诉我为什么会这样?
From the docs for communicate
:从用于
communicate
的文档:
Interact with process: Send data to stdin.
与进程交互:将数据发送到标准输入。 Read data from stdout and stderr, until end-of-file is reached.
从 stdout 和 stderr 读取数据,直到到达文件结尾。 Wait for process to terminate.
等待进程终止。
So after communicate()
runs, the process has been terminated .因此,在
communicate()
运行后,该进程已终止。
If you want to write and read without waiting for the process to stop:如果您想在不等待进程停止的情况下进行写入和读取:
Don't ever use shell=True
- it needlessy invokes a shell to in turn call your program, so there will be another process between you and your program.永远不要使用
shell=True
- 它不必要地调用一个 shell 来调用你的程序,所以你和你的程序之间会有另一个进程。 That has lots of unpleasant side-effects.这有很多令人不快的副作用。 The default is
shell=False
so you should stick with that.默认是
shell=False
所以你应该坚持下去。 Change your Popen
line to:将您的
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)
Use p.stdin.write
to write to the process.使用
p.stdin.write
写入进程。 Use p.stdout.read
to read from it.使用
p.stdout.read
从中读取。
p.stdout.read
if there's nothing to read will block.p.stdout.read
会阻塞。 Calling p.stdin.write
if the write buffer is full will block.p.stdin.write
将阻塞。 So you have to make sure you have something to read/write - you do that on unix OS by using select
.select
做到这一点。 On windows you unfortunately must resort to threads.Popen.communicate
does internally.Popen.communicate
在内部所做的。AO_FelixStrategy_UnitTest
then you have possible additional problems:AO_FelixStrategy_UnitTest
那么您可能会遇到其他问题:
AO_FelixStrategy_UnitTest
buffers.AO_FelixStrategy_UnitTest
缓冲区。 By default standard C PIPE communication is buffered so you may not see any output until after you've closed the input side (by doing p.stdin.close()
. Unless AO_FelixStrategy_UnitTest
flushes the output periodically.p.stdin.close()
。除非AO_FelixStrategy_UnitTest
定期刷新输出。 Here's some example code, based on what you describe.这是一些示例代码,基于您的描述。 It could work depending on how
AO_FelixStrategy_UnitTest
was developed:它可以根据
AO_FelixStrategy_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()
reads data from stdout and stderr until end-of-file is reached . communicate()
从标准输出和标准错误读取数据,直到到达文件结尾。 - It waits until your program quits. - 它一直等到你的程序退出。
comunicate will only run once and then will close the pipe, therefore if you want to send several commands to it you need to send one after the other in the same string . comunicate只会运行一次,然后会关闭管道,因此如果您想向它发送多个命令,您需要在同一个字符串中一个接一个地发送。
Here is an example that worked for me after some investigation, trying threads, subprocess32, stdin.write, stdout.read etc etc. This information is not in the official python reference information for communicate: https://docs.python.org/2/library/subprocess.html这是经过一些调查后对我有用的示例,尝试了线程、subprocess32、stdin.write、stdout.read 等。此信息不在用于通信的官方 python 参考信息中: https ://docs.python.org/ 2/library/subprocess.html
The only place where I found this out was here: Python subprocess communicate kills my process我发现这一点的唯一地方是在这里: Python subprocess communication kills my process
Here is the code, it is simple, no threads, no subprocess32, works on linux and windows.这是代码,它很简单,没有线程,没有 subprocess32,适用于 linux 和 windows。 Yes you have to know how many times to send commands to the other process but in general you do know that.
是的,您必须知道向另一个进程发送命令的次数,但通常您确实知道这一点。 On top of this you can add threads, cwd, shell=True or anything else you may want but this is the simplest case:
在此之上,您可以添加线程、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
So for example if you want to send multiple carriage returns (\\n) to the application being called and the a param in the middle (interactively mind you) you would call it something like this:因此,例如,如果您想向被调用的应用程序发送多个回车符 (\\n) 以及中间的 a 参数(交互式地提醒您),您可以这样称呼它:
cmd_parms = "\n\n\n\n\nparm\n\n"
errcode, out, err = do_commands(command, cmd_parms)
Hope it helps.希望能帮助到你。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.