将 Python 标准 IO 公开给子进程

Expose Python standard IO to Subprocess

本文关键字:子进程 IO Python 标准      更新时间:2023-10-16

在Python 3.5.1上,我有以下内容:

output = subprocess.check_output(cmd).decode(encoding="UTF-8")

这会将正确调用的命令cmdcmd 中的 C++14 代码如下所示:

HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
assert(handle!=INVALID_HANDLE_VALUE); //Always passes
assert(handle!=nullptr);              //Always passes
CONSOLE_SCREEN_BUFFER_INFO csbi;
BOOL result = GetConsoleScreenBufferInfo(handle,&csbi);
assert(result!=0); //Always fails.  `GetLastError()` returns 6 (invalid handle) 

运行上述 Python 代码会导致子进程cmd在指示的行处失败。 根据 Python 文档,在这种情况下,stdout/stderr 应该继承自父进程(即 Python 解释器)。 所以,它不应该。 事实上,上述工作得很好,例如 printf 编辑输出。

尝试显式重定向也会失败:

#Traceback (most recent call last):
#  File "C:devPython35libsubprocess.py", line 914, in __init__
#    errread, errwrite) = self._get_handles(stdin, stdout, stderr)
#  File "C:devPython35libsubprocess.py", line 1145, in _get_handles
#    c2pwrite = msvcrt.get_osfhandle(stdout.fileno())
#io.UnsupportedOperation: fileno
p = subprocess.Popen(cmd.split(" "),stdout=sys.stdout,stderr=sys.stderr)
#Using `subprocess.PIPE` instead fails in the same way as the `subprocess.check_output(...)`
#example originally given above.
出了

什么问题? 我该如何解决?

管道不是控制台。 check_output()内部使用stdout=PIPE。它不会重定向控制台输出(由 WriteConsoleW() 生成)。

第一个错误(无效句柄)表明标准输出不是控制台设备。

除非是所需的行为(在标准输出之外打印);如果 stdout 不是控制台设备,请使用WriteFile()

第二个错误(io.UnsupportedOperation: fileno)表明sys.stdout不是真正的文件,因此您不能将其作为参数传递给子进程stdout(您可以使用stdout=PIPE重定向子进程的stdout并使用print()sys.stdout.write()方法直接打印输出)。