为什么python.subprocess在proc.communicate()之后挂起?

时间:2010-03-09 11:35:22

标签: python subprocess

我有一个名为my_own_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'有点被忽略了。

有谁能让我知道为什么会这样?

3 个答案:

答案 0 :(得分:27)

来自docs for communicate

  

与流程交互:将数据发送到stdin。从stdout和stderr读取数据,直到达到文件结尾。 等待进程终止。

因此,communicate()运行后,该流程已终止

如果您想在不等待进程停止的情况下进行写入和阅读:

  • 不要永远使用shell=True - 它无需调用shell来依次调用您的程序,因此您和程序之间会有另一个进程。这有很多令人不快的副作用。默认值为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将阻止。如果写缓冲区已满,则调用p.stdin.write将阻止。因此,您必须确保有一些可读/写的内容 - 您可以使用select在unix OS上执行此操作。在Windows上,你不幸的是必须求助于线程。至少这是内部Popen.communicate的作用。
  • 如果您没有写AO_FelixStrategy_UnitTest,那么您可能会遇到其他问题:
    • 它可能是从其他地方读取,而不是标准输入。有些程序直接从终端读取,其他程序使用一些OS API来读取。这意味着写入stdin的数据不会进入程序。对于密码提示,这通常是正确的。
    • 请记住,您必须考虑AO_FelixStrategy_UnitTest缓冲区。默认情况下,标准C PIPE通信是缓冲的,因此在您关闭输入端之前可能看不到任何输出(通过执行p.stdin.close()。除非AO_FelixStrategy_UnitTest定期刷新输出。

这是一些示例代码,基于您描述的内容。根据{{​​1}}的开发方式,它可以发挥作用:

AO_FelixStrategy_UnitTest

答案 1 :(得分:4)

communicate()从stdout和stderr 读取数据,直到到达文件结尾。 - 等待你的程序退出。

答案 2 :(得分:1)

通信 只运行一次 ,然后关闭管道,因此如果要向其发送多个命令,则需要在< strong> 相同字符串

这是一个在经过一些调查后尝试使用的示例,尝试了thread,subprocess32,stdin.write,stdout.read等等。这些信息不在官方python参考信息中进行通信:https://docs.python.org/2/library/subprocess.html

我发现这一点的唯一地方是: Python subprocess communicate kills my process

无论如何这里是代码,简单,没有线程,没有subprocess32,适用于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),并在中间发送一个参数(交互式地提醒您),您可以将其称为:

cmd_parms = "\n\n\n\n\nparm\n\n"

errcode, out, err = do_commands(command, cmd_parms)
相关问题