繁体   English   中英

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

[英]why does python.subprocess hang after proc.communicate()?

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

谁能告诉我为什么会这样?

用于communicate文档

与进程交互:将数据发送到标准输入。 从 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将阻塞。 所以你必须确保你有一些东西可以读/写 - 你可以在 unix OS 上使用select做到这一点。 不幸的是,在 Windows 上,您必须求助于线程。 至少这是Popen.communicate在内部所做的。
  • 如果您没有编写AO_FelixStrategy_UnitTest那么您可能会遇到其他问题:
    • 它可能是从其他地方读取,而不是标准输入。 有些程序直接从终端读取,有些程序使用一些 OS API 来读取。 这意味着写入 stdin 的数据不会进入程序。 对于密码提示,这通常是正确的。
    • 请记住,您必须考虑AO_FelixStrategy_UnitTest缓冲区。 默认情况下,标准 C PIPE 通信是缓冲的,因此在关闭输入端之前您可能看不到任何输出(通过执行p.stdin.close() 。除非AO_FelixStrategy_UnitTest定期刷新输出。

这是一些示例代码,基于您的描述。 它可以根据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()从标准输出和标准错误读取数据,直到到达文件结尾 - 它一直等到你的程序退出。

comunicate只会运行一次,然后会关闭管道,因此如果您想向它发送多个命令,您需要在同一个字符串中一个接一个地发送。

这是经过一些调查后对我有用的示例,尝试了线程、subprocess32、stdin.write、stdout.read 等。此信息不在用于通信的官方 python 参考信息中: https ://docs.python.org/ 2/library/subprocess.html

我发现这一点的唯一地方是在这里: Python subprocess communication 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) 以及中间的 a 参数(交互式地提醒您),您可以这样称呼它:

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

errcode, out, err = do_commands(command, cmd_parms)

希望能帮助到你。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM