python中的subprocess.PIPE上的非阻塞读取
我正在使用子进程模块启动子进程并连接到它的输出流(stdout)。我希望能够在其stdout上执行非阻塞读取。有没有办法让.readline非阻塞或在我调用ѭ0之前检查流上是否有数据?我希望这是可移植的,或至少在Windows和Linux下工作。
这是我现在如何做的(如果没有可用的数据,它会在ѭ0上阻塞):
p = subprocess.Popen('myprogram.exe', stdout = subprocess.PIPE)
output_str = p.stdout.readline()
没有找到相关结果
已邀请:
26 个回复
佩疵瓦
,
,
在这种情况下无济于事。 无论操作系统如何,无阻塞地读取流的可靠方法是使用
:
辽躺
阻塞并且没有超时。如果主要功能已经完成并且不再需要等待进一步的用户输入,我通常希望我的程序退出,但它不能,因为
仍然在等待一行的另一个线程中阻塞。我发现这个问题的解决方案是使用fcntl模块使stdin成为非阻塞文件:
在我看来,这比使用选择或信号模块解决这个问题要清晰一点,但是它再一次只适用于UNIX ...
乏摩纶誊伟
模块。 这种方法类似于@Bryan Ward的基于
的答案 - 定义一个协议,一旦数据准备就调用它的方法:
请参阅文档中的“子流程”。 有一个高级接口
返回
对象,允许使用
协同程序异步读取一行 (使用
/
Python3.5+语法):
执行以下任务: 启动子进程,将其stdout重定向到管道 异步读取子进程'stdout中的一行 杀死子进程 等它退出 如有必要,每个步骤都可以通过超时秒限制。
锯康
该模块负责S.Lott建议的所有线程。
吞睫素
类,并覆盖
方法。 Twisted(取决于所使用的反应器)通常只是一个很大的
循环,其中安装了回调来处理来自不同文件描述符(通常是网络套接字)的数据。所以
方法只是安装一个回调来处理来自
的数据。演示此行为的简单示例如下:
Twisted文档有一些很好的信息。 如果你围绕Twisted构建整个应用程序,它会与本地或远程的其他进程进行异步通信,就像这样非常优雅。另一方面,如果你的程序不是建立在Twisted之上,那么这实际上并没有那么有用。希望这对其他读者有帮助,即使它不适用于您的特定应用程序。
联课
对于readline() - 如:
骨乏唯瓜
目浆搽
现在你可以这样做:
您也可以将它与RequestHandler一起使用
貉骂
为什么现有解决方案不起作用: 需要readline的解决方案(包括基于Queue的解决方案)始终会阻塞。杀死执行readline的线程很困难(不可能?)。它只会在创建它的进程完成时被杀死,但不会在生成输出的进程被终止时被杀死。 正如aonnn所指出的,将低级别fcntl与高级别readline调用混合可能无法正常工作。 使用select.poll()是很整洁,但根据python docs在Windows上不起作用。 使用第三方库对此任务来说似乎过度,并添加了其他依赖项。
购藏盗码韦
联海
babsoft
荤碗
的详细信息都归功于@ techtonik的回答。 在Unix和Windows系统上都有一个稍微修改过的版本。 Python3兼容(只需要很小的改动)。 包括posix版本,并定义要用于其中的例外。 这样,您可以对Unix和Windows代码使用相同的函数和异常。
为了避免读取不完整的数据,我最终编写了自己的readline生成器(返回每行的字节串)。 它是一个发电机,所以你可以...
懊毁暗
视蕉梁拌客
宦哨抹存胳
。有关示例和完整文档,请参阅项目页面。
雇砰
锯康
醒荒捆府绣
踩什不
邵酮
辩谷变充
函数调用。 我同意这些文档令人困惑,并且这种常见的脚本编写任务的实现很尴尬。我相信旧版本的python有不同的默认值
和不同的解释,因此造成了很多混乱。这似乎适用于Python 2.7.12和3.5.2。 关键是将
设置为行缓冲,然后将
设置为文本文件而不是二进制文件,这似乎是设置
时的默认值。
ERROR,DEBUG和VERBOSE只是将输出打印到终端的宏。 这个解决方案是IMHO 99.99%有效,因为它仍然使用阻塞
函数,所以我们假设子过程很好并输出完整的行。 我欢迎反馈来改进解决方案,因为我还是Python的新手。
闲窍
模块从IO流中“读取任何可用数据”。此功能最初会阻塞,直到数据可用,但随后只读取可用且不会进一步阻塞的数据。 鉴于它使用
模块,这只适用于Unix。 该代码完全符合PEP8标准。
公藕
埠仙俊
观察者是
主程序设置ping然后调用gobject邮件循环。
任何其他工作都附加到gobject中的回调。
剃摧庭峨僳