首页 > 解决方案 > 用于用户输入的python子进程

问题描述

我想从新终端的子进程中获取用户输入。

    import subprocess
    additionalBuildArguments = "defaultarg1"
    proc = subprocess.Popen(["python", "user_input.py", additionalBuildArguments],
                            creationflags=subprocess.CREATE_NEW_CONSOLE,
                            stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    try:
        outs, errs = proc.communicate(timeout=15)
    except subprocess.TimeoutExpired:
        proc.kill()
        outs, errs = proc.communicate()
    additionalBuildArguments = outs or additionalBuildArguments

用户输入.py:

import sys

arg = sys.argv[1]
user_input = input(f"Additional build arguments [{arg}] (Push <ENTER> to use these settings):\n")
print(user_input)

只要我不设置stdout=subprocess.PIPE和/或stderr=subprocess.PIPE选项,我就可以输入输入。但是使用这些选项,我无法将任何输入写入控制台。实际上,我需要这些选项来重定向标准输出,以访问父进程中打印的user_input。有谁知道这里有什么问题?

标签: pythonsubprocesspipe

解决方案


请注意,我不明白您为什么要这样做,并且本能地觉得您不应该这样做。但是,这是完全可能的:只捕获stdout

import sys
from subprocess import run
print("Type away: ", end="")
sys.stdout.flush()
r = run(["python", "-c", "print(input())"], capture_output=True, encoding="utf8")
print(f"You entered {r.stdout}")

编辑显然你正在使用 Windows。根据文档,您的标志在shell=True. 这对我有用shell=True,但我不知道它是否适合你:

import sys
from subprocess import run
print("Type away: ", end="")
sys.stdout.flush()
r = run("python -c 'print(input())'", capture_output=True, shell=True, encoding="utf8")
print(f"You entered {r.stdout}")

这可以链接以在第三个进程中运行,这将需要从子进程中打印同时捕获标准输出。但在这一点上,我们正处于非常可怕的黑客领域。

一个更好但仍然很老套的解决方案是重新表述问题。您想生成一个终端,显然您可以这样做,并且用户可以正确地与之交互,然后您希望在生成代码中从该终端获取输出。 STDOUT不是此通信的正确通道。就我个人而言,我会像这样构造我的代码:

在生成代码中:

  • 生成参数化脚本以在生成的终端中运行并将其保存为临时文件
  • spawn 子终端运行生成的脚本
  • 等待完成
  • 读取临时文件并获取数据
  • 删除临时脚本和临时输出文件

在生成的代码中:

  • 尽可能多地做(毕竟你有一个完整的python)
  • 将输出作为 json 转储到临时文件

这仍然是 hacky,但它只涉及生成一个终端。请注意,我仍然不明白您为什么要这样做,但这至少应该有效


推荐阅读