Python subprocess communicate调用需按键退出的外部程序时挂起求助
问题:Python调用控制台可执行文件时
communicate挂起或进程残留的解决思路 我尝试在Python程序中集成一款控制台可执行文件,它会基于输入文件完成计算、在控制台输出结果并生成若干文本文件,最后要求用户按任意键退出。由于不想重新编译该可执行文件,遇到如下问题:
exe_path = 'Fourier/Fourier.exe' cwd_path = 'Fourier' process = Popen(exe_path, cwd=cwd_path, stdin=PIPE, stdout=PIPE, stderr=PIPE) (stdout, stderr) = process.communicate(b"\r\n")
程序可正常启动,但会在process.communicate处挂起;若移除最后一行代码,程序可运行但会残留于后台。
问题原因
communicate挂起:该exe最后的"按任意键退出"逻辑大概率是通过getch()(Windows平台)这类直接读取控制台按键的函数实现,而非读取标准输入stdin。此时通过communicate传入的\r\n无法被识别,进程会一直等待有效按键输入。- 进程残留:移除
communicate后,exe仍处于等待按键的状态,未正常退出,因此会留在后台。
解决思路
1. 模拟物理按键输入(针对getch类等待)
如果exe使用getch()获取按键,需要通过Windows API模拟按键操作,依赖pywin32库:
import win32api import win32con from subprocess import Popen, CREATE_NEW_CONSOLE import time exe_path = 'Fourier/Fourier.exe' cwd_path = 'Fourier' # 创建独立控制台窗口,确保按键能被exe捕获 process = Popen(exe_path, cwd=cwd_path, creationflags=CREATE_NEW_CONSOLE) # 等待exe完成计算(根据实际运行时间调整等待时长,也可用process.poll()循环检查状态) time.sleep(3) # 模拟按下并释放Enter键 win32api.keybd_event(win32con.VK_RETURN, 0, 0, 0) win32api.keybd_event(win32con.VK_RETURN, 0, win32con.KEYEVENTF_KEYUP, 0) # 等待进程完全退出 process.wait()
2. 分阶段处理输入输出(针对stdin读取场景)
如果exe是通过stdin等待输入,可分阶段读取输出直到出现按键提示,再发送输入:
from subprocess import Popen, PIPE exe_path = 'Fourier/Fourier.exe' cwd_path = 'Fourier' # 启用文本模式,方便按行读取输出 process = Popen( exe_path, cwd=cwd_path, stdin=PIPE, stdout=PIPE, stderr=PIPE, text=True ) # 循环读取输出,直到出现按键提示(需替换为exe实际的提示文本) while True: line = process.stdout.readline() if not line: break print(line.strip()) if "按任意键退出" in line: break # 发送Enter键并刷新缓冲区 process.stdin.write("\n") process.stdin.flush() # 获取剩余输出并等待进程退出 stdout, stderr = process.communicate() print(stdout) print(stderr)
3. 利用Windows CMD命令自动处理
通过cmd /c start /wait命令让系统接管exe的等待逻辑,无需手动处理输入:
from subprocess import call exe_path = 'Fourier/Fourier.exe' cwd_path = 'Fourier' # 用CMD启动exe并等待其完全退出 call(f'cmd /c start /wait "" "{exe_path}"', cwd=cwd_path)
内容的提问来源于stack exchange,提问作者rok
相关产品推荐
相关产品推荐

