Python使用subprocess时stdout.readline()阻塞挂起问题如何解决
subprocess调用Python实例stdout.readline()阻塞问题解决方案
阻塞的根本原因
- 子进程Python的输出缓冲机制:当stdout通过管道连接到其他进程时,Python默认启用全缓冲,只有缓冲区满、进程退出或主动flush时才会输出内容。你之前仅在父进程执行flush操作,无法操作子进程内部的缓冲区,因此无效。
readline()的终止规则:该方法必须读到换行符\n才会结束读取并返回结果,你测试脚本中sys.stdout.write('glorp')输出的内容没有携带换行符,即便内容流出缓冲区,readline()也会继续挂起等待。- 子进程输入未终止:你向子进程stdin写入代码后,没有发送EOF标识,子进程会一直处于等待输入状态,不会主动结束执行并刷出缓冲内容。
修复后可运行代码
from subprocess import Popen, PIPE, STDOUT # 子进程输出内容加换行,写完主动刷缓冲 script = "import sys;sys.stdout.write('glorp\\n');sys.stdout.flush()\n" # 启动子进程时添加-u参数,禁用输出缓冲 p = Popen([r"C:\Program Files\Python37\python.exe", "-u"], stdin=PIPE, stdout=PIPE, text=True) p.stdin.write(script) # 关闭stdin发送EOF,通知子进程输入结束 p.stdin.close() print("readline") print(p.stdout.readline()) print("end")
改动说明
- 给子进程输出的内容末尾添加
\n,匹配readline()的读取终止规则,避免无意义的等待。 - 子进程执行write操作后主动调用
sys.stdout.flush(),强制将内容从进程内缓冲区写入管道。 - 启动子进程时添加
-u启动参数,强制Python子进程的stdin/stdout采用无缓冲模式,从根源避免内容滞留在进程内部。 - 父进程写入完执行脚本后调用
p.stdin.close(),给子进程发送EOF信号,子进程收到后会执行完现有代码后退出,不会继续等待后续输入。
内容的提问来源于stack exchange,提问作者Anti-Distinctlyminty
相关产品推荐
相关产品推荐

