简体   繁体   English

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

[英]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从中读取。

  • Calling 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 .所以你必须确保你有一些东西可以读/写 - 你可以在 unix OS 上使用select做到这一点。 On windows you unfortunately must resort to threads.不幸的是,在 Windows 上,您必须求助于线程。 At least that is what Popen.communicate does internally.至少这是Popen.communicate在内部所做的。
  • If you didn't write AO_FelixStrategy_UnitTest then you have possible additional problems:如果您没有编写AO_FelixStrategy_UnitTest那么您可能会遇到其他问题:
    • It could be reading from somewhere else, not standard input.它可能是从其他地方读取,而不是标准输入。 Some programs read directly from the terminal, others use some OS API to read.有些程序直接从终端读取,有些程序使用一些 OS API 来读取。 That means data written to stdin won't go to the program.这意味着写入 stdin 的数据不会进入程序。 This is often true for password prompts.对于密码提示,这通常是正确的。
    • Remember that you have to account for 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.默认情况下,标准 C PIPE 通信是缓冲的,因此在关闭输入端之前您可能看不到任何输出(通过执行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.

相关问题 proc.communicate()的输出不格式化django python中的换行符 - Output of proc.communicate() does not format newlines in django python Popen 不接受 proc.communicate 的输入,如何执行 function 要求输入 python 的密码? - Popen does not take input from proc.communicate how to execute function that asks for a password with python? 为什么在不同线程中调用asyncio subprocess.communicate会挂起? - Why does asyncio subprocess.communicate hang when called in different thread? 为什么Python在子进程中运行mpirun时会挂起? - Why does Python hang when running mpirun within a subprocess? 为什么Python子进程的这种简单用法会挂起? - Why does this simple usage of Python's subprocess hang? 为什么在通信()完成后子进程继续运行? - Why does subprocess keep running after communicate() is finished? Python subprocess.Popen poll 似乎挂起但通信有效 - Python subprocess.Popen poll seems to hang but communicate works python.subprocess(cppBinaryExe)是否会损害cppBinaryExe的性能? - Will python.subprocess(cppBinaryExe) compromise cppBinaryExe's performance? 如何获取 Python.subprocess 中的丢包值 - How can I get the packet loss value in Python.subprocess 终止后,Python子进程通信失败 - Python Subprocess communicate fails after terminate
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM