Python使用subprocess获取可执行文件实时输出时部分程序日志为空如何解决
代码失效原因
- 遗漏了标准错误输出采集:你当前代码将
stderr设置为subprocess.DEVNULL,而包括nanominer在内的很多命令行工具会把运行日志、状态信息输出到标准错误流而非标准输出流,这部分内容被直接丢弃。 - 程序输出缓冲问题:当可执行文件检测到输出目标不是交互式终端时,默认会开启全缓冲机制,只有输出内容攒满缓冲区才会真正输出,你调用
readline()时会因为没有完整行输出一直拿不到内容,直到程序被杀死也没采集到任何输出。 - 文件缓冲区未落地:你打开log.txt后没有主动调用
flush()也没有正常关闭文件,就算采集到了输出,内容可能还留在Python的文件缓冲区里,没有写入磁盘,导致日志文件为空。
修复后的代码
import subprocess def CreateLog(executable, timeout=5): # 把stderr合并到stdout,同时开启行缓冲 process = subprocess.Popen( executable, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, bufsize=1 ) try: # 等待进程执行结束,超时自动抛出异常,直接读取所有输出 output, _ = process.communicate(timeout=timeout) except subprocess.TimeoutExpired: # 超时后杀死进程,读取剩余所有输出 process.kill() output, _ = process.communicate() # 用with上下文管理器自动处理文件关闭和缓冲落地 with open("log.txt", "w", encoding="utf-8") as f: f.write(output)
补充说明
- 如果调整后还是拿不到输出,可以尝试给Popen添加参数
env={"PYTHONUNBUFFERED":"1"},针对Python编写的可执行文件强制关闭缓冲;如果是其他语言编写的程序,可以用第三方库pexpect模拟终端交互,强制程序按行输出。 - 如果你要保留原来的逐行写入逻辑,需要在每次
f.write(output)后调用f.flush(),强制把内容写入磁盘,避免留在缓冲区。
内容的提问来源于stack exchange,提问作者Mohzy
相关产品推荐
相关产品推荐

