微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

subprocess stdin PIPE不会返回,直到程序终止

我一直在尝试解决subprocess.PIPE与子stream程没有运气。

我试图将命令传递给一个始终运行的进程,并接收结果,而不必每次都closures/打开进程。

这里是主要的启动代码

launcher.py:

在Windows中捕获4K屏幕并直接保存到缓冲区

如何绑定winjs中的repeater元素的点击事件?

如何为绝对的初学者制作Windows的Python扩展

如何分割一个大的XML文件

在QueryInterface()实现中调用AddRef()的正确方法

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'printrn') process.stdin.flush() time.sleep(10)

listener.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()都会写入。 会发生什么事情:当循环closures并且程序终止时,所有内容都会写入,或者SIGTERM / CTRL-C脚本。

我在Windows 8 Python 3.4中运行这个。

这几乎就像标准input缓冲区,直到进程closures,然后通过。 我有buffsize = 0设置,我正在冲洗,所以这对我没有意义。 我以为任何一个都足够了。

subprocess运行在不同的进程中,所以发起程序中的睡眠不应该对subprocess产生影响。

有没有人有任何想法,为什么这是封锁?

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

也就是说,在程序运行时键入控制台时,没有任何内容写入文件

stdinreader.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没有帮助,因为我没有控制subprocess的刷新方式(这将是我的返回subprocess.PIPE)。 也许如果我用open('wb')重新初始化PIPE,它将不会缓冲。 我会尝试。

更新2:我似乎已经将这个问题隔离到正在调用的subprocess,写入标准输出之后不会刷新。

有没有什么办法可以强制刷新父和子之间的PIPE而不修改subprocess? 该subprocess是magick.exe(imagemagick 7)与args ['-script,' – ']运行。 从subprocess的angular度来看,它有一个<_io.TextIOWrapper name =''mode ='w'encoding ='cp1252'>的stdout对象。 我猜这个subprocess只会在初始化时打开认的stdout对象,我们不能真正控制它是否缓冲。

奇怪的是,传递孩子正常的sys.stdout对象,而不是subprocess.PIPE写入后不需要.flush()的subprocess。

CreateCaret颜色错了?

在导入的多处理器子类上使用.start()时发生IOerror

如何增加python的进程优先级

如何在调用SelectItem函数时强制CTreeCtrl不滚动到该项目?

如何在Window中保留自定义文本(Win32)

程序的运行方式有所不同,具体取决于它们是从控制台还是通过管道运行。 如果控制台(一个python进程可以用os.stdin.isatty()检查),标准输出数据是行缓冲的,你可以及时看到数据。 如果一个管道,标准输出数据是块缓冲,你只有看到数据,当堆积了很多或程序刷新管道。

当你想抓取程序输出时,你必须使用管道,程序以缓冲模式运行。 在linux上,你可以通过创建一个假的控制台来欺骗程序(伪tty,pty,…)。 pty模块,pexpect和其他人都这样做。

在窗户上,我不知道有什么办法可以使它工作。 如果你控制正在运行的程序,经常刷新。 否则,在Windows徽标上肆意炫耀。 如果你想早点结束,你甚至可以在下次相亲时提到这个问题。 但我再也想不起来了。

(如果有人知道一个修复程序,我想听到它,我已经看到一些代码,试图打开一个Windows控制台和屏幕刮,但这些解决方案不断丢失数据。它应该工作,如果有一个回环字符设备在那里)。

问题是被调用的子进程在写入标准输出后没有刷新。 感谢JF和tdelaney指引我正确的方向。 我已经向这里的开发者提出了这个问题: http : //www.imagemagick.org/discourse-server/viewtopic.PHP?f=2&t= 26276& p=115545#p115545

除了修改子进程源代码之外,在Windows中似乎还没有解决这个问题的方法。 也许如果你把子进程的输出重定向一个可能工作的NamedTemporaryFile,但是我没有测试它,我想它会被锁在Windows中,所以只有一个父和子可以一次打开它。 不是无法克服,但烦人。 也许还有一种方法可以通过stdbuf的unixutils port来执行应用程序,或者类似于JF所建议的: Python C程序子进程挂在“for it it iter”

如果您有权访问您所调用的子进程的源代码,则可以始终使用禁用的缓冲来重新编译它。 在C:中停用stdout很简单:

setbuf(stdout,NULL)

或者设置每行缓冲而不是块缓冲:

setvbuf(stdout,(char *) NULL,_IOLBF,0);

另请参见: Python C程序子进程挂在“for it it iter”

希望这有助于其他人在路上。

你可以尝试关闭在listener.py结束的管道? 我认为这是问题

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐