Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2008/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么python.subprocess在proc.communicate()之后挂起?_Python_Subprocess - Fatal编程技术网

为什么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=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操作系统上使用
    select
    。不幸的是,在windows上,您必须求助于线程。至少这是Popen.Communication内部所做的
  • 如果您没有编写
    AO_FelixStrategy\u UnitTest
    ,则可能存在其他问题:
    • 它可以从其他地方读取,而不是标准输入。一些程序直接从终端读取,另一些程序使用一些操作系统API读取。这意味着写入stdin的数据不会进入程序。对于密码提示,这通常是正确的
    • 请记住,您必须考虑
      AO\u FelixStrategy\u UnitTest
      buffers。默认情况下,标准C管道通信是缓冲的,因此在关闭输入端之前,您可能看不到任何输出(通过执行
      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中做了一些模糊相似的工作,我想知道如何更好-半衰期。