Windows 上的 Python 子进程输出? [英] Python subprocess output on windows?

查看:30
本文介绍了Windows 上的 Python 子进程输出?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在从子进程标准输出管道获取输出时遇到了一些困难.我正在通过它启动一些第三方代码,以提取日志输出.直到最近更新第三方代码,一切正常.更新后,python 开始无限期阻塞,实际上并没有显示任何输出.我可以手动启动第三方应用程序并查看输出.

I'm running into some difficulties getting output from a subprocess stdout pipe. I'm launching some third party code via it, in order to extract log output. Up until a recent update of the third party code, everything worked fine. After the update, python has started blocking indefinitely, and not actually showing any output. I can manually launch the third party app fine and see output.

我正在使用的代码的基本版本:

A basic version of the code I'm using:

import subprocess, time
from threading import Thread

def enqueue_output(out):
    print "Hello from enqueue_output"
    for line in iter(out.readline,''):
        line = line.rstrip("\r\n")
        print "Got %s" % line
    out.close()

proc = subprocess.Popen("third_party.exe", stdout=subprocess.PIPE, bufsize=1)
thread = Thread(target=enqueue_output, args=(proc.stdout,))
thread.daemon = True
thread.start()

time.sleep(30)

如果我将此脚本替换为third_party.exe,这将非常有效:

This works perfectly if I substitute third_party.exe for this script:

import time, sys

while True:
    print "Test"
    sys.stdout.flush()
    time.sleep(1)

所以我不清楚需要用魔法来使这个与原始命令一起工作.

So I'm unclear as to magic needs to be done to get this working with the original command.

这些都是 subprocess.Popen 行的变体,我试过没有成功:

These are all variants of the subprocess.Popen line I've tried with no success:

proc = subprocess.Popen("third_party.exe", stdout=subprocess.PIPE, bufsize=0)
proc = subprocess.Popen("third_party.exe", stdout=subprocess.PIPE, shell=True)
proc = subprocess.Popen("third_party.exe", stdout=subprocess.PIPE, creationflags=subprocess.CREATE_NEW_CONSOLE)
si = subprocess.STARTUPINFO()
si.dwFlags = subprocess.STARTF_USESTDHANDLES | subprocess.STARTF_USESHOWWINDOW
proc = subprocess.Popen("third_party.exe", stdout=subprocess.PIPE, startupinfo=si)

在这种情况下,我实际上不能使用 .communicate() .我启动的应用程序仍会运行很长时间(几天到几周).我实际测试 .communicate() 的唯一方法是在应用启动后不久将其杀死,我认为这不会给我有效的结果.

Edit 1: I can't actually use .communicate() in this case. The app I'm launching remains running for long periods of time (days to weeks). The only way I could actually test .communicate() would be to kill the app shortly after it launches, which I don't feel would give me valid results.

即使是非线程版本也失败了:

Even the non-threaded version of this fails:

import subprocess, time
from threading import Thread

proc = subprocess.Popen("third_party.exe", stdout=subprocess.PIPE, stderr=subprocess.PIPE)

print "App started, reading output..."
for line in iter(proc.stdout.readline,''):
    line = line.rstrip("\r\n")
    print "Got: %s" % line

感谢 jdi,以下工作正常:

Edit 2: Thanks to jdi, the following works okay:

import tempfile, time, subprocess

w = "test.txt"
f = open("test.txt","a")
p = subprocess.Popen("third_party.exe", shell=True, stdout=f,
                        stderr=subprocess.STDOUT, bufsize=0)

time.sleep(30)

with open("test.txt", 'r') as r:
    for line in r:
        print line
f.close()

推荐答案

首先,我建议您简化此示例以确保您可以真正阅读任何内容.从混合中去除线程的复杂性:

First I would recommend that you simplify this example to make sure you can actually read anything. Remove the complication of the thread from the mix:

proc = subprocess.Popen("third_party.exe", stdout=subprocess.PIPE, bufsize=1)
print proc.communicate()

如果有效,那就太好了.那么您可能在如何直接或可能在您的线程中读取标准输出方面遇到问题.

If that works, great. Then you are having problems possibly with how you are reading the stdout directly or possibly in your thread.

如果这不起作用,您是否也尝试过将 stderr 管道传输到 stdout?

If this does not work, have you tried piping stderr to stdout as well?

proc = subprocess.Popen("third_party.exe", 
                        stdout=subprocess.PIPE, 
                        stderr=subprocess.STDOUT, bufsize=1)

更新

既然你说 communicate() 是死锁,这里是另一种方法,你可以尝试看看它是否与子进程的内部缓冲区有问题...

Since you say communicate() is deadlocking, here is another approach you can try to see if its a problem with the internal buffer of subprocess...

import tempfile
import subprocess

w = tempfile.NamedTemporaryFile()
p = subprocess.Popen('third_party.exe', shell=True, stdout=w, 
                        stderr=subprocess.STDOUT, bufsize=0)

with open(w.name, 'r') as r:
    for line in r:
        print line
w.close()

这篇关于Windows 上的 Python 子进程输出?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆