如何捕获python子进程的管道执行中的中间错误

时间:2018-11-08 22:09:38

标签: python subprocess pipe

用python doc替换shell管道,我有一段代码像这样。

p1 = Popen(["tac" , "/var/log/some_process_log.output"], stderr=PIPE, stdout=PIPE)
p2 = Popen(["head", "-n", "1000"], stdin=p1.stdout, stdout=outfile)
p1.stdout.close()  # Allow p1 to receive a SIGPIPE if p2 exits.
output = p2.communicate()[0]

outfile是我要重定向head命令输出的位置。日志文件很大,因此我在上面做一个“头”

链接就像p1 | p2 | p3 | ..... | Pn > outfile

如果执行p1时发生错误,例如用户对/var/log/some_process_log.output文件没有读取权限,当我执行p1.stderr

时,不会传递Pn.communicate()中的错误消息

如果我在每个阶段都执行p1.stderr.readline(),则需要long time to process。 pydocs中提到了这一点:

  

注意:读取的数据缓存在内存中,因此,如果以下情况不要使用此方法   数据大小很大或没有限制。

我避免使用subprocess.check_output,因为它不处理管道并且需要不安全的shell=True

任何帮助将不胜感激。谢谢

1 个答案:

答案 0 :(得分:0)

您可以使用以下方法创建单独的管道:

import os
errread, errwrite = os.pipe()

然后将所有stderr实例的写端设置为Popen

p1 = Popen(["tac" , "/var/log/some_process_log.output"], stderr=errwrite, stdout=PIPE)
p2 = Popen(["head", "-n", "1000"], stdin=p1.stdout, stderr=errwrite, stdout=outfile)

记住完成后要关闭写结束:

os.close(errwrite)

并通过以下任一方式获取错误消息:

data_group = os.read(errread, buf_size)

或:

import io
data = io.open(errread, 'rb', buf_size).read()