【发布时间】:2019-08-05 05:13:55
【问题描述】:
我有一个脚本,它是自动化测试套件的一部分。它在 Windows 上运行非常缓慢,但在 Linux 上却没有,我已经找到了原因。我们正在测试的进程('frank')创建了一个子进程(所以是一个孙子进程)。在该孙子进程也结束之前,python 代码不会返回(在 Windows 上 - 在 Linux 上不这样做)。如果没有父进程,孙进程将在 5 秒后杀死自己(它会挂起以防另一个进程与它交谈)
我发现如果我不捕获标准输出,我可以阻止通信功能以这种方式挂起。但我需要标准输出。我在某处读到通信功能正在等待所有管道关闭。我知道孙子的标准输出句柄是重复的,但我无法更改我正在测试的代码。
我一直在寻找解决方案。我尝试了一些创建标志(仍在代码中)但没有帮助。
这是缩减测试-
import os
import sys
import threading
import subprocess
def read_from_pipe(process):
last_stdout = process.communicate()[0]
print (last_stdout)
CREATE_NEW_PROCESS_GROUP = 0x00000200
DETACHED_PROCESS = 0x00000008
# start process
command = 'frank my arguments'
cwd = "C:\\dev\\ui_test\\frank_test\\workspace\\report183"
p = subprocess.Popen(command,
stdout=subprocess.PIPE,
cwd=cwd)
# run thread to read from output
t = threading.Thread(target=read_from_pipe, args=[p])
t.start()
t.join(30)
print('finished')
有什么想法吗?
谢谢。
彼得。
【问题讨论】:
-
不要打扰
communicate,因为您只使用stdout。等待子进程退出,然后在句柄上调用PeekNamedPipe(来自msvcrt.get_osfhandle(p.stdout.fileno()))以获取可供读取的字节数。尝试读取比可用内容更多的内容会阻塞,因为它是一个同步模式文件,并且管道有另一个潜在的写入者,即孙进程。 -
如果您需要获取的不仅仅是一个充满数据的管道(默认为 4 KiB),那么请使用一个循环来轮询
PeekNamedPipe并在子进程运行时读取可用数据。 -
@eryksun 我还有点儿戏。如果我等待进程以“p.wait()”结束,我会遇到与通信相同的问题。它一直等到孙子完成。
-
谢谢 - 我想我把你的“等待”这个词的字面意思是 .wait 调用!我现在查看了民意调查并通过一个小循环进行了尝试。这如我所愿——我的意思是,poll() 告诉我这个过程已经结束,即使孙子还活着。我会看看你的其余建议。我一直希望有一个简单的旗帜或其他东西! :-)
-
我使用的是 python 3.x。我不确定究竟是哪个子版本,因为这个测试系统通常在一些我必须检查的构建机器上运行。
标签: python windows subprocess pipe stdout