Skip to main content
 首页 » 编程设计

Python 子进程和标准输出之程序死锁

2025年02月15日36luoye11

我有一个模拟程序,它通过 stdin 进行试验并向 stdout 提供输出

做一个 C++/Qt 程序在 QProcess 中运行它效果很好。

做一个 Python 程序在 linux 下运行它效果很好,使用:

p = subprocess.Popen(cmd,stdin=subprocess.PIPE,stdout=subprocess.PIPE) 

并使用p.stdin.write、p.stdout.readline和p.wait

但是,在windows下,程序正常运行并通过stdin获取命令(已通过调试子进程验证),但python程序死锁在任何 p.stdout.readline 和 p.wait 处。如果移除 stdout=subprocess.PIPE 参数,程序运行,输出显示在控制台上,不会发生死锁。

这听起来很熟悉来自 Python 文档的警告:

Warning : This will deadlock when using stdout=PIPE and/or stderr=PIPE and the child process generates enough output to a pipe such that it blocks waiting for the OS pipe buffer to accept more data. Use communicate() to avoid that.

但是,我不能使用 communicate(),因为程序协议(protocol)不是单个命令和单个输出,而是需要多个命令和回复。

有什么解决办法吗?

请您参考如下方法:

不确定,但它看起来像是一个缓冲 问题。在 Linux 上(与大多数 Unix 或类 Unix 一样),文件或管道的输出在操作系统级别进行内部缓冲。这意味着在 write 调用之后,所有数据都被缓冲,但管道的另一端没有任何可用数据,直到内部缓冲区已满、数据被刷新或管道关闭。这就是为什么发明了 pty 而没有用管道对实现的原因之一。

换句话说,如果您需要使用以前的输出来知道应该使用管道输入什么,则不可能驱动程序,除非该程序是通过在读取任何内容之前始终刷新其输出而专门为其量身定制的。它在真正的终端(tty 或 pty)上工作,因为在同一设备上进行任何读取之前,驱动程序会自动强制刷新输出。

但这与您在问题中引用的文档中描述的 dealock 不同。