【问题标题】:python subprocess hangs when stderr is piped当 stderr 被管道传输时,python 子进程挂起
【发布时间】:2014-10-26 18:21:15
【问题描述】:

我将 java 程序作为子进程运行,但是当我将 stderr 重定向到管道时,程序挂起。例如myProcess = subprocess.Popen(cmd, shell=True, stdout = subprocess.PIPE) 有效,但myProcess = subprocess.Popen(cmd, shell=True, stdout = subprocess.PIPE, stderr=subprocess.PIPE)hangs。

我运行的命令类似于:

java -DSomeVals -classpath <somevals> package.Name

Stderr 会生成大量输出,我记得在某处读过 shell=True 可能会导致死锁。不幸的是,当我设置 shell=False 时,我收到一条错误消息,指出文件名太长。

我尝试了myProcess = subprocess.Popen(['java', args], shell=False, stdout = subprocess.PIPE, stderr = subprocess.PIPE),但随后 java 抱怨它找不到我要运行的类。

我想管道 stderr,因为它弄乱了我的程序的输出。

【问题讨论】:

  • 你之后如何处理管道中的数据?大多数 python 文档都说要使用通信,但如果您不关心从 stderr 中输出什么,则将其设置为 stderr=open("/dev/null")(实际上不要这样做,它会泄漏文件描述符),否则您需要使用communicate() 之类的东西从两个管道中啜饮,以防止输出触发死锁。
  • 我调用了通信,但只有在进程运行了大约 5 分钟之后(产生我需要的结果需要很长时间)。与此同时,该应用每隔几秒就会写入一条日志消息。

标签: java python


【解决方案1】:

我认为你只需要从管道中读取。管道缓冲区正在填满并阻塞进程。查看这个重复“HelloWorld”50,000 次的示例。

import subprocess
import os

def getLinesFromShellCommand(command):
    p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=os.getcwd())
    lines = []
    for curLine in p.stdout.readlines():
        lines.append(curLine)
    p.wait()
    return lines


print "Starting..."
lines = getLinesFromShellCommand("printf 'HelloWorld\n%.0s' {1..50000}")
for curLine in lines:
    print curLine,

【讨论】:

    猜你喜欢
    • 2018-03-11
    • 1970-01-01
    • 1970-01-01
    • 2015-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多