python - 用于用户输入的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。有谁知道这里有什么问题?
解决方案
请注意,我不明白您为什么要这样做,并且本能地觉得您不应该这样做。但是,这是完全可能的:只捕获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,但它只涉及生成一个终端。请注意,我仍然不明白您为什么要这样做,但这至少应该有效。
推荐阅读
- r - R - 将 DFM 转换为 LSA,然后计算余弦相似度:Error inherits(x, "Matrix") is not TRUE
- google-cloud-logging - Google Cloud Logging 身份验证/权限
- r - 患者在 R 中表现良好的编程概率
- r - 如何逐行识别数据帧中的未知模式?
- jquery - 大数值以指数格式显示 Kendo jquery 树列表
- swift - 如何在 Swift 中合并 2 个 pdf 矢量图像资源
- django - 我如何在 django 和 windows 中编写 redis 通道层
- c# - EF 映射具有不同列类型的两个实体
- ios - 在 iOS 共享扩展 (Xamarin) 中将带有 byte[] 的类添加到 NSUserDefaults
- android - 观察从后台线程进行的数据库对象更改