简体   繁体   English

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

[英]Python subprocess & stdout - program deadlocks

I have a simulation program which is piloted though stdin and provides output to stdout我有一个模拟程序,它通过 stdin 进行引导,并向 stdout 提供输出

Doing a C++/Qt program for running it in a QProcess works well.做一个C++/Qt程序在 QProcess 中运行它效果很好。

Doing a Python program for running it under linux works well, using:做一个在linux下运行它的Python程序效果很好,使用:

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

And using p.stdin.write , p.stdout.readline , and p.wait并使用p.stdin.writep.stdout.readlinep.wait

However, under windows , the program runs and gets the commands through stdin as it should(this has been verified by debugging the subprocess), but the python program deadlocks at any p.stdout.readline , and p.wait .然而,在windows下,程序运行并通过标准输入获取命令(这已通过调试子进程验证),但 python 程序在任何p.stdout.readlinep.wait处死锁。 If the stdout=subprocess.PIPE parameter is removed, the program works, the output is displayed on the console and no deadlock occurs.如果去掉stdout=subprocess.PIPE参数,则程序运行,控制台显示输出,不会发生死锁。

This sounds familiar with a warning from the Python documentation:这听起来很熟悉 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.警告:当使用 stdout=PIPE 和/或 stderr=PIPE 并且子进程生成足够的输出到管道时,这将死锁,从而阻止等待 OS 管道缓冲区接受更多数据。 Use communicate() to avoid that.使用communication() 来避免这种情况。

However, I can't use communicate(), as the program protocol is not a single command and a single output, rather several commands and replies are required.但是,我不能使用communication(),因为程序协议不是单个命令和单个输出,而是需要多个命令和回复。

Is there any solution?有什么解决办法吗?

Unsure of it, but it looks like a buffering problem.不确定,但它看起来像一个缓冲问题。 On Linux (as on most Unix or Unix-like), output to a file or a pipe is internally buffered at the OS level.在 Linux 上(就像在大多数 Unix 或类 Unix 上一样),文件或管道的输出在操作系统级别进行内部缓冲。 That means that after a write call, all the data is buffered but nothing is available at the other end of the pipe until either the internal buffer is full, the data is flushed or the pipe is closed.这意味着在write调用之后,所有数据都被缓冲,但管道的另一端没有可用的数据,直到内部缓冲区已满、数据被刷新或管道关闭。 That's one of the reasons why pty s were invented and are not implemented with a pipe pair.这就是为什么pty被发明并且没有用管道对实现的原因之一。

Said differently, it is not possible to drive a program where you need to use previous output to know what you should give as input with pipes, unless the program has been specially tailored for it by consistently flushing its output before reading anything.换句话说,在需要使用以前的输出来知道应该使用管道作为输入提供什么的情况下,驱动程序是不可能的,除非该程序是专门为它量身定制的,在读取任何内容之前始终刷新其输出。 It works on a true terminal (tty or pty) because the driver automatically forces a flush of the output before any read on the same device.它适用于真正的终端(tty 或 pty),因为在同一设备上进行任何读取之前,驱动程序会自动强制刷新输出。

But it is not the same dealock that is described in the documentation that you have cited in your question.但这与您在问题中引用的文档中描述的 delock 不同。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM