Python subprocess流式读取程序stdout运行30分钟后挂死问题咨询
问题解答
缓冲区满是否会导致挂死
你猜测的「do_something处理速度慢导致stdout缓冲区满引发挂死」的情况不会发生。
subprocess.PIPE由操作系统内核维护,当缓冲区满时,阻塞的是写端(即你的传感器采集程序),它会停在stdout写操作等待缓冲区释放,不会影响读端(Python程序)的读操作。你当前遇到的读端阻塞等待下一行输出,说明内核缓冲区里没有能匹配行结束符的完整数据,和写端阻塞无关。
其他可能的挂死诱因
- 采集程序输出无换行的半行内容:你用
for line in proc.stdout迭代是严格按行读取,只有读到换行符\n才会返回一行内容。如果采集程序某次输出的内容不包含换行符,哪怕主动执行了flush,Python的读行逻辑也会一直阻塞等待后续内容拼接成完整行,看起来就是挂死。 - 采集程序异常退出未释放文件描述符:如果采集程序崩溃、变成僵尸进程,没有正常关闭stdout文件描述符,Python读端不会收到EOF信号,会一直无期限等待数据,不会抛出异常。
- Python侧流缓冲设置问题:你当前代码没有开启文本模式,也没有指定行缓冲,
proc.stdout默认是二进制全缓冲模式,即便内核有数据,也可能因为缓冲没满不会返回给上层逻辑。 - 采集程序自身卡顿:传感器读取逻辑、硬件异常可能导致采集程序本身停止输出数据,自然读端就不会拿到新内容。
排查建议
- 挂死时首先检查采集进程的运行状态,确认是仍在正常运行、还是已经崩溃/变成僵尸状态。
- 临时把
do_something替换为空逻辑,若还是挂死即可完全排除处理速度慢的影响。 - 修改Popen参数,添加
text=True, bufsize=1开启行缓冲文本模式,降低缓冲带来的影响:
with subprocess.Popen( run_my_program, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, text=True, bufsize=1 ) as proc: for line in proc.stdout: do_something(line)
- 增加超时检测逻辑,用
select模块监控stdout的可读事件,超时后打印状态排查是采集程序无输出还是读逻辑卡住。
内容的提问来源于stack exchange,提问作者Jeff L
相关产品推荐
相关产品推荐

