subprocess.check_call隐藏子进程输出失效原因及获取输出方法问询
关于subprocess.check_call屏蔽子进程输出失效及获取输出的问题
问题描述
使用subprocess.check_call调用外部脚本时,尝试通过stdout=subprocess.DEVNULL和stderr=subprocess.DEVNULL屏蔽控制台输出,但仍有部分输出显示:其中一个脚本仅屏蔽stderr有效,另一个仅屏蔽stdout有效。代码如下:
subprocess.check_call(cmd, timeout=timeout_sec, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
同时需要了解如何获取子进程的stdout或stderr。
屏蔽输出失效的原因
- 部分脚本可能直接写入终端设备(如
/dev/tty),而非标准输出/错误流,这种情况下stdout和stderr的重定向不会生效,因为它们绕开了这两个标准流。 - 当使用
shell=True时,如果cmd是多命令组合(比如管道、分号分隔的命令),可能部分命令的输出没有被正确重定向——比如某些命令会显式指定输出目标,不受父进程的重定向设置影响。 - 旧版本Python中
subprocess.DEVNULL的实现可能存在bug,导致重定向不完全。
彻底屏蔽所有输出的方法
如果是脚本直接写终端的情况,可以在shell层面做全局重定向,强制将所有输出导向空设备:
import os # 根据系统选择空设备路径 null_device = "nul" if os.name == "nt" else "/dev/null" # 在原命令后追加shell重定向语法,覆盖所有输出 cmd = f"{cmd} >{null_device} 2>&1" subprocess.check_call(cmd, timeout=timeout_sec, shell=True)
获取子进程的stdout或stderr
仅捕获stdout
使用subprocess.check_output,它会返回子进程的stdout内容;若需要屏蔽stderr,可将其导向DEVNULL:
# 仅捕获stdout,屏蔽stderr stdout_content = subprocess.check_output(cmd, timeout=timeout_sec, shell=True, stderr=subprocess.DEVNULL) # 合并捕获stdout和stderr combined_content = subprocess.check_output(cmd, timeout=timeout_sec, shell=True, stderr=subprocess.STDOUT)
分别捕获stdout和stderr
使用Python 3.5+新增的subprocess.run,可单独捕获两个流的内容:
result = subprocess.run(cmd, timeout=timeout_sec, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) # 获取标准输出内容 stdout_content = result.stdout # 获取标准错误内容 stderr_content = result.stderr # 模拟check_call的异常抛出逻辑(返回码非0时触发) if result.returncode != 0: raise subprocess.CalledProcessError(result.returncode, cmd, output=result.stdout, stderr=result.stderr)
内容的提问来源于stack exchange,提问作者Cezar
相关产品推荐
相关产品推荐

