从check_output禁止stdout,但改为将其写入日志

时间:2018-12-06 21:45:56

标签: python logging subprocess stdout

我有以下代码:

try:
    subprocess.check_output(command.split())
except subprocess.CalledProcessError as e:
    count_failure.increment()
    logger.error(e.__dict__)
    return

check_output()失败时,我想从stdout中禁止该消息,而是将其写入我的logger

现在,标准输出错误消息弄乱了我的tqdm进度栏:

[hobbes3@hobbes3 bin]$ ./mass_index.py
34%|█████████████████████████████████████████▋                                                                                | 13/38 [00:00<00:14,  1.75it/s]
unable to open file: path='/mnt/data/samples/irs_990/foo.xml' error='Permission denied'
100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 38/38 [00:02<00:00,  5.96it/s]

此外,实际消息Permission denied也不存储在e内部。我的e.__dict__只说

{'returncode': 22, 'cmd': ['/opt/splunk/bin/splunk', 'add', 'oneshot', '/mnt/data/samples/irs_990/foo.xml', '-index', 'main', '-sourcetype', 'irs_990'], 'output': b'', 'stderr': None}

1 个答案:

答案 0 :(得分:5)

那是因为您正在运行的命令正在向标准错误流发出错误消息。

check_output仅捕获标准的输出,除非您使用其他参数。所以:

subprocess.check_output(command.split(),stderr=subprocess.STDOUT)

所以输出中也有错误,或者(python 3):

subprocess.check_output(command.split(),stderr=subprocess.DEVNULL)

完全消除此错误消息。

要获取带有标准错误的适当异常消息,您将不得不将错误流重定向到特定管道,这样就不必使用stderr=None

subprocess.check_output(command.split(),stderr=subprocess.PIPE)

但是,这可能会导致输出流和错误流之间的死锁(取决于程序输出到输出还是错误的方式,如果没有以灵巧的方式读取管道(例如,使用线程),则可能由于缓冲区而阻止一次写入当您正在阅读另一个为空时已满)。

在您的情况下,最好使用subprocess.Popencommunicate更好地处理该情况(使用线程或在其下起作用的任何东西)

p = subprocess.Popen(command.split(),stderr=subprocess.PIPE,stdout=subprocess.PIPE)
output,error = p.communicate()

(并保持相同的异常处理)