使用Python subprocess调用Fortran.exe时遇输入报错求助
解决Python subprocess调用老Fortran程序的输入错误问题
问题分析
你遇到的fmt: end of file错误,是Fortran程序读取标准输入(unit 5)时发现输入提前结束导致的。结合测试情况来看:
subprocess.run()能正常支持手动输入,说明程序本身功能正常- 添加
stdin=subprocess.PIPE后报错,说明输入传递的格式或时机不符合程序预期,常见原因包括:- 换行符不匹配(Windows控制台程序期望
\r\n而非\n) - 输入缓冲未及时刷新,导致程序等待输入时缓冲区为空
- 老程序可能直接读取控制台硬件输入,而非标准输入流
- 换行符不匹配(Windows控制台程序期望
基础解决方案:调整subprocess参数与输入格式
先尝试修正输入传递方式,确保程序能正确接收输入:
代码示例
import subprocess program_path = r"D:\PGE\~CIP\code\wain12.exe" # 构造输入序列:每个输入项后添加Windows标准换行符\r\n,确保程序识别为回车 input_sequence = [ "输入值1", "输入值2", "输入值3" ] input_data = "\r\n".join(input_sequence) + "\r\n" # 末尾额外加回车,确保程序接收完所有输入 # 启动进程:禁用shell,使用text模式自动处理编码和换行,无缓冲确保输入立即发送 process = subprocess.Popen( program_path, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, bufsize=0 ) # 发送输入并等待程序结束 stdout, stderr = process.communicate(input=input_data) # 打印输出和错误信息用于调试 print("程序输出:") print(stdout) if stderr: print("错误日志:") print(stderr)
关键调整说明
text=True:自动处理字符串与字节的转换,同时在Windows环境下自动适配控制台的\r\n换行要求,无需手动编码。bufsize=0:关闭输入缓冲,确保输入内容立即发送给Fortran程序,避免程序因等待输入超时触发EOF错误。- 捕获
stdout/stderr:防止程序因输出缓冲区满而阻塞,导致输入无法正常传递。 - 避免
shell=True:减少不必要的shell解析层,避免路径或参数的意外解析错误。
备选方案:模拟控制台输入(针对直接读取控制台的老程序)
如果上述方法无效,说明该Fortran程序可能没有读取标准输入,而是直接读取控制台硬件输入。此时需要用Windows API模拟用户手动输入:
步骤1:安装依赖
pip install pywin32
代码示例
import win32api import win32con import win32process import win32gui import subprocess import time program_path = r"D:\PGE\~CIP\code\wain12.exe" # 启动程序并创建独立控制台窗口 process = subprocess.Popen( program_path, creationflags=subprocess.CREATE_NEW_CONSOLE ) # 等待程序启动,确保窗口加载完成 time.sleep(1) # 根据进程ID获取程序控制台窗口句柄 def get_console_window(pid): window_handles = [] def enum_windows_callback(hwnd, extra): _, window_pid = win32process.GetWindowThreadProcessId(hwnd) if window_pid == pid and win32gui.GetWindowText(hwnd): extra.append(hwnd) return True win32gui.EnumWindows(enum_windows_callback, window_handles) return window_handles[0] if window_handles else None console_hwnd = get_console_window(process.pid) if not console_hwnd: print("无法找到程序控制台窗口") exit() # 将控制台窗口设为前台,确保输入生效 win32gui.SetForegroundWindow(console_hwnd) # 模拟键盘输入函数:发送字符串+回车 def send_console_input(text): # 逐个字符发送按键事件 for char in text: vk_code = win32api.VkKeyScan(char) win32api.keybd_event(vk_code, 0, 0, 0) win32api.keybd_event(vk_code, 0, win32con.KEYEVENTF_KEYUP, 0) # 模拟回车按键 win32api.keybd_event(win32con.VK_RETURN, 0, 0, 0) win32api.keybd_event(win32con.VK_RETURN, 0, win32con.KEYEVENTF_KEYUP, 0) # 按顺序发送输入 send_console_input("输入值1") time.sleep(0.5) # 等待程序处理输入 send_console_input("输入值2") time.sleep(0.5) send_console_input("输入值3") # 等待程序执行完成 process.wait()
说明
这种方法完全模拟用户手动操作控制台的行为,适用于任何依赖控制台输入的老程序,但需要注意:
- 程序启动后需要等待足够时间确保窗口加载完成
- 输入间隔时间可能需要根据程序响应速度调整
内容的提问来源于stack exchange,提问作者alamkelana
相关产品推荐
相关产品推荐

