何时调用subprocess.communicate()?代码正确性及调用位置咨询
代码问题分析与修正
这段代码存在明显问题,p.communicate()的调用位置也不恰当,具体问题和修正方案如下:
核心问题
- 死锁风险:直接调用
p.stderr.readline()却未处理stdout输出,若进程向stdout写入大量内容导致缓冲区填满,进程会被阻塞无法继续执行,进而readline()也会一直卡住,无法获取后续内容或让进程正常退出。 - 混合读取逻辑冲突:
communicate()的作用是一次性读取完stdout和stderr的所有数据、等待进程结束并设置returncode。你在调用它之前手动读取了一行stderr,这种混合手动读管道和communicate()的方式会破坏subprocess的安全处理机制,容易引发不可预期的输出截断或进程阻塞问题。
修正后的代码
应该先通过communicate()获取所有输出,再从中提取stderr的第一行,示例如下:
import subprocess # 注意:优先使用系统独立的time二进制文件(通常是/usr/bin/time),避免依赖shell内置命令 p = subprocess.Popen(['/usr/bin/time', '-p', 'ls'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout_data, stderr_data = p.communicate() # 提取stderr的第一行 first_stderr_line = stderr_data.decode('utf-8').splitlines()[0] if stderr_data else '' print(first_stderr_line) print(f'exitcode: {p.returncode}')
额外说明
如果你的系统中time是bash等shell的内置命令,直接用列表形式调用会找不到命令,此时可以添加shell=True(但需注意参数传递改为字符串格式),不过更推荐直接调用/usr/bin/time来避免shell依赖。
内容的提问来源于stack exchange,提问作者Alexey Starinsky
相关产品推荐
相关产品推荐

