gpt4 book ai didi

python - 子进程标准输入 PIPE 直到程序终止才返回

转载 作者:可可西里 更新时间:2023-11-01 09:59:03 31 4
gpt4 key购买 nike

我一直在尝试排除带有子进程的 subprocess.PIPE 问题,但没有成功。

我正在尝试将命令传递给始终运行的进程并接收结果,而不必每次都关闭/打开进程。

这是主要的启动代码:

启动器.py:

import subprocess
import time

command = ['python', 'listener.py']
process = subprocess.Popen(
command, bufsize=0,
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
)

# simulates sending a new command every 10 seconds
for x in range(1,10):
process.stdin.write(b'print\r\n')
process.stdin.flush()
time.sleep(10)

监听器.py:

import sys

file = open('log.txt', 'w+')
while True:
file.write(sys.stdin.read(1))
file.close()

这被简化为显示相关片段。最后,我将让线程监听 stdout 和 stderr,但现在我正在尝试解决基础问题。

我期望发生的事情:对于 launcher.py 中的每个循环,listener.py 中的 file.write() 都会写入。相反会发生什么:当循环关闭并且程序终止时,或者我 SIGTERM/CTRL-C 脚本时,一切都会写入。

我在 Windows 8 Python 3.4 中运行它。

这几乎就像 stdin 缓冲直到进程关闭然后它通过。我设置了 buffsize=0,我正在冲洗,所以这对我来说没有意义。我认为其中一个就足够了。

子进程在不同的进程中运行,因此启动器中的 sleep 应该不会影响子进程。

有人知道为什么会阻塞吗?

更新 1:从控制台 (python.exe stdinreader.py) 运行以下代码也会看到相同的行为

也就是说,当您在程序运行时输入控制台时,不会向文件写入任何内容。

标准输入读取器.py:

import sys
import os

file = open('log.txt', 'w+b')
while True:
file.write(sys.stdin.read(1))
file.close()

在 file.write() 之前添加一个 file.flush() 可以解决这个问题,但这对子进程没有帮助,因为我无法控制子进程的刷新方式(这将是我的返回 subprocess.PIPE ).也许如果我用 open('wb') 重新初始化那个 PIPE,它就不会缓冲。我会努力的。

更新 2:我似乎已将此问题隔离到被调用的子进程,该子进程在写入 stdout 后未刷新。

在不修改子进程的情况下,我可以做些什么来强制刷新父子进程之间的标准输出 PIPE? 子进程是 magick.exe (imagemagick 7),使用 args ['-script , '-']。从子进程的角度来看,它有一个标准输出对象 <_io.TextIOWrapper name='' mode='w' encoding='cp1252'>。我猜子进程只会在初始化时打开默认的 stdout 对象,我们无法真正控制它是否缓冲。

奇怪的是,将普通的 sys.stdout 对象而不是 subprocess.PIPE 传递给子进程需要在写入后将子进程传递给 .flush()。

最佳答案

程序的运行方式不同,具体取决于它们是从控制台运行还是通过管道运行。如果控制台(python 进程可以使用 os.stdin.isatty() 检查),stdout 数据是行缓冲的,您会立即看到数据。如果是管道,stdout 数据是 block 缓冲的,您只能在堆积了相当多的数据或程序刷新管道时才能看到数据。

当你想抓取程序输出时,你必须使用管道并且程序以缓冲模式运行。在 Linux 上,您可以通过创建一个假控制台(伪 tty、pty、...)来欺骗程序。 pty 模块、pexpect 和其他模块可以做到这一点。

在 Windows 上,我不知道有什么方法可以让它工作。如果您控制正在运行的程序,请经常刷新它。否则,徒劳地盯着 Windows Logo 。如果你想让它早点结束,你甚至可以在下次相亲时提到这个问题。但我想不出更多了。

(如果有人知道修复方法,我很想听听。我看到一些代码试图打开 Windows 控制台并对其进行屏幕抓取,但这些解决方案不断丢失数据。如果有的话,它应该可以工作某处的环回字符设备)。

关于python - 子进程标准输入 PIPE 直到程序终止才返回,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25965332/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com