【问题标题】:How to capture intermediate error in python subprocess's piped execution如何在 python 子进程的管道执行中捕获中间错误
【发布时间】:2019-04-12 12:03:33
【问题描述】:

按照 python doc 替换 shell-pipeline,我有一段看起来像这样的代码。

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 文件的读取权限,当我执行Pn.communicate() 时,p1.stderr 中的错误消息不会通过管道传输

如果我在每个阶段都执行 p1.stderr.readline(),那么它需要 long time to process。这在 pydocs 中有提到:

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

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

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

【问题讨论】:

    标签: python subprocess pipe


    【解决方案1】:

    你可以创建一个单独的管道:

    import os
    errread, errwrite = os.pipe()
    

    并将所有Popen 实例的写入端设置为stderr

    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()
    

    【讨论】:

    • 请注意,所有错误数据仍然缓存在内存中。
    猜你喜欢
    • 2013-08-01
    • 2021-02-22
    • 1970-01-01
    • 1970-01-01
    • 2011-08-04
    • 1970-01-01
    • 1970-01-01
    • 2018-07-12
    • 2019-06-10
    相关资源
    最近更新 更多