linux - python subprocess.run 如果你重新定向 stdout/stderr,它会错误退出而不是工作

标签 linux python-3.x subprocess

#!/usr/bin/env python3

import subprocess
import os

if False:
    # create log file.
    kfd = os.open( 'kk.log', os.O_WRONLY )

    # redirect stdout & err to a log file.
    os.close(1)
    os.dup(kfd)
    os.close(2)
    os.dup(kfd)

subprocess.run([ "echo", "hello world"], check=True )

% ./kk.py
hello world
% 

以上工作正常,但如果您尝试编辑文件,并将 False 替换为 true:

% ./kk.py
% more kk.log
Traceback (most recent call last):
File "./kk.py", line 16, in <module>
  subprocess.run([ "echo", "hello world"], check=True )
File "/usr/lib/python3.6/subprocess.py", line 418, in run
  output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command '['echo', 'hello world']' returned 

非零退出状态1。 %

我们没有得到输出,进程错误退出... 我希望它能正常工作,写入 kk.log。

最佳答案

你可能想这样说:

#!/usr/bin/env python3

import subprocess
import os

if True:
    # create log file.
    kfd = os.open( 'kk.log', os.O_WRONLY | os.O_CREAT )

    # redirect stdout & err to a log file.
    os.dup2(kfd, 1)
    os.dup2(kfd, 2)

subprocess.run([ "echo", "hello world"], check=True )

注意 os.dup2 的使用.有两个原因。首先,生成的文件描述符是可继承的。您的 echo 实际上没有打开 stdout/-err,因此失败了(您可以在 shell 中运行以下命令以仅关闭 stdout 来回显以检查行为:/bin/echo hello world 1>&-).另请注意,如果我关闭 stdout (1),最低描述符(和 os.dup 的结果)可能并不总是为 1。有人可能已经关闭了您的 stdin (0) 在运行脚本之前(同样适用于 stderr)。

文件描述符继承的背景故事在 PEP-446 中.

我还添加了 os.O_CREAT,因为我尝试重现您的问题的第一次失败是不存在的 kk.log。

不用说,除非尝试在操作系统中使用接口(interface)(也许作为练习),否则我想您通常应该坚持 subprocess 本身。

关于linux - python subprocess.run 如果你重新定向 stdout/stderr,它会错误退出而不是工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51234966/

相关文章:

python - 如何打印等间距的数据?

Python 子进程超时终止

c++ - 使用 Eclipse 在 Windows 中为 Linux 编译 C++ 程序?

python - 通过子进程库使用 python 执行进程

python - PyOpenSSL 与 ffi.from_buffer(b"") 错误

Python 子进程包返回损坏的管道

python - Python 中子进程 PIPE 的非阻塞读取,一次一个字节

linux - 将 tee 与 bash 结合使用会导致某些脚本挂起

linux - 在裸板上移植 linux

python - 正则表达式给出元组而不是完全匹配