Windows 上的 Python 子进程输出?

标签 python windows subprocess

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

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

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 代替这个脚本,这将完美地工作:

import time, sys

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

所以我不清楚是否需要完成魔法才能使它与原始命令一起工作。

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

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)

编辑 1: 在这种情况下我实际上不能使用 .communicate() 。我启动的应用程序会持续运行很长时间(数天到数周)。我可以实际测试 .communicate() 的唯一方法是在应用程序启动后不久将其终止,我认为这不会给我有效的结果。

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

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

编辑 2: 感谢 jdi,以下工作正常:

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()

最佳答案

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

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

如果可行,那就太好了。那么您可能会遇到直接或可能在您的线程中读取标准输出的方式的问题。

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

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

更新

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

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 子进程输出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10406532/

相关文章:

python - 如何找到Qt库位置

python - 如果我在 Python 脚本运行时修改它会发生什么?

python - 针对 Windows 计算机使用 impacket 的 SMB 客户端时“无法请求 session ”

python - 添加可见的GPU设备时遇到问题:0

c - 文件与句柄 - 这两件事有什么区别

c++ - 相当于 VirtualAlloc() 的 _set_new_handler?

windows - 创建快捷方式以使用 Powershell 运行 Powershell

python - subprocess.check_output() 没有输出

python - 在 python 中将输出捕获为 tty

rust - 在 Rust 中写入子进程的标准输入?