为何fileinput.input无法作为subprocess.run的stdin?如何解决?
问题原因与解决方案
为什么fileinput.input作为subprocess.run的stdin会挂起?
fileinput.input()返回的是FileInput类实例,它仅模拟了文件对象的部分接口(如read()、readline()),并非真正的操作系统级文件描述符对象,也未实现fileno()方法。
当subprocess.run()接收这类无有效文件描述符的对象时,Python会启动后台线程读取该对象并写入子进程管道,但FileInput的内部迭代机制导致线程无法正确识别EOF(文件结束标记),子进程会一直等待输入,最终程序挂起。
如何传递多文件合并内容给子进程?
根据文件大小,可选择以下两种方案:
方案1:内存合并(适合小文件)
先将所有文件内容读入内存,再传递给子进程,实现简单:
import fileinput import subprocess import sys from io import BytesIO idle_path = sys.exec_prefix + "/bin/idle3" paths = [idle_path] # 读取所有文件内容到二进制内存对象 combined_content = BytesIO() with fileinput.input(paths, mode='rb') as f: combined_content.write(f.read()) combined_content.seek(0) # 重置读取指针到开头 subprocess.run(["cat"], stdin=combined_content)
方案2:流式传递(适合大文件)
通过管道流式写入内容,避免占用大量内存:
import fileinput import subprocess import sys idle_path = sys.exec_prefix + "/bin/idle3" paths = [idle_path] # 启动子进程并创建输入管道 proc = subprocess.Popen(["cat"], stdin=subprocess.PIPE) # 分块读取多文件内容并写入管道 with fileinput.input(paths, mode='rb') as f: for chunk in iter(lambda: f.read(4096), b''): proc.stdin.write(chunk) proc.stdin.close() # 关闭管道,告知子进程输入结束 # 等待子进程执行完成 proc.wait()
适配你的实际需求(cantools plot)
针对你需要调用cantools plot的场景,使用流式传递方案更适合日志文件:
import fileinput import subprocess import sys # 配置实际参数 dbc_path = "/path/to/vehicle.dbc" candump_paths = ["path/to/candump1.log", "path/to/candump2.log"] # 启动cantools plot子进程 proc = subprocess.Popen( [sys.executable, "-m", "cantools", "plot", dbc_path], stdin=subprocess.PIPE ) # 流式写入所有candump文件内容 with fileinput.input(candump_paths, mode='rb') as f: for chunk in iter(lambda: f.read(4096), b''): proc.stdin.write(chunk) proc.stdin.close() proc.wait()
内容的提问来源于stack exchange,提问作者Joooeey
相关产品推荐
相关产品推荐

