Python subprocess新终端获取用户输入 重定向stdout/stderr后无法输入求解
问题根因
subprocess.CREATE_NEW_CONSOLE标志创建的新控制台窗口,默认会绑定子进程的stdin/stdout/stderr三个标准流:新窗口的键盘输入会传递给子进程的stdin,子进程的输出也会直接打印在这个新窗口中。- 当你显式设置
stdout=subprocess.PIPE、stderr=subprocess.PIPE时,相当于强行把子进程的stdout、stderr重定向到父子进程之间的匿名管道,不再关联到新控制台的输出缓冲区。同时子进程的stdin会默认继承父进程的标准输入流,而非绑定到新控制台的输入设备:你在新弹出的控制台窗口输入的内容不会被传递到子进程的input()函数,input()会一直阻塞等待父进程的输入,直观表现就是新终端无法输入、卡死。 - 额外存在缓冲问题:就算你调整了
stdin的绑定,子进程的print()输出如果是写入管道的,默认会开启全缓冲模式,不会立刻把内容刷到管道给父进程,也可能导致父进程拿不到输出。
可行解决方案
如果要同时实现「新终端窗口可输入」+「父进程拿到子进程的输出结果」,推荐用临时文件中转结果的方案,不需要重定向任何标准流,稳定性更高,调整后的代码如下:
父进程代码
import subprocess import tempfile import os additionalBuildArguments = "defaultarg1" # 创建临时文件存储用户输入结果 with tempfile.NamedTemporaryFile(mode='w+', delete=False, encoding='utf-8') as f: temp_file_path = f.name proc = subprocess.Popen( ["python", "user_input.py", additionalBuildArguments, temp_file_path], creationflags=subprocess.CREATE_NEW_CONSOLE ) proc.wait() # 读取子进程写入的结果 with open(temp_file_path, 'r', encoding='utf-8') as f: user_input = f.read().strip() additionalBuildArguments = user_input or additionalBuildArguments # 清理临时文件 os.unlink(temp_file_path)
子进程user_input.py代码
import sys arg = sys.argv[1] temp_file_path = sys.argv[2] user_input = input(f"Additional build arguments [{arg}] (Push <ENTER> to use these settings):\n") # 把用户输入写入临时文件,不需要打印到stdout with open(temp_file_path, 'w', encoding='utf-8') as f: f.write(user_input)
内容的提问来源于stack exchange,提问作者Simon Rechermann
相关产品推荐
相关产品推荐

