【问题标题】:python replacing shell pipelinepython替换shell管道
【发布时间】:2018-06-12 12:08:47
【问题描述】:

关于示例found here

output=`dmesg | grep hda`

变成:

p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
p1.stdout.close()  # Allow p1 to receive a SIGPIPE if p2 exits.
output = p2.communicate()[0]

如何将其扩展为 3 流程管道?

另外,我找不到 p1.stdout.close() 到底是做什么的?如果 p1 运行时间长了怎么办?它会在应用 close() 之前等待 p1 完成吗?

close() 必须在communicate() 之前?

我是否正确理解在调用communicate() 之前,管道已设置,但“暂停”?或者更确切地说,每个进程都立即并行启动,但需要从标准输入输入的进程在调用communicate() 之前一直阻塞?


考虑:

output=`dmesg | grep hda | grep bla`

可能是这样的:

p1 = Popen(["dmesg"], stdout=PIPE)
p1.stdout.close()  # Allow p1 to receive a SIGPIPE if p2 exits.

p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
p2.stdout.close()  # Allow p2 to receive a SIGPIPE if p3 exits.

p3 = Popen(["grep", "bla"], stdin=p2.stdout, stdout=PIPE)

output = p3.communicate()[0]

(上面那个在当前表单中以ValueError: I/O operation on closed file 崩溃)

这个不会报错,但是因为我不理解close(),所以可能是以后某个时间末日的设置:

p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)

p1.stdout.close()  # Allow p1 to receive a SIGPIPE if p2 exits.

p3 = Popen(["grep", "bla"], stdin=p2.stdout, stdout=PIPE)

p2.stdout.close()  # Allow p2 to receive a SIGPIPE if p3 exits.

output = p3.communicate()[0]

或者这个:

p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
p3 = Popen(["grep", "bla"], stdin=p2.stdout, stdout=PIPE)

p1.stdout.close()  # Allow p1 to receive a SIGPIPE if p2 exits.
p2.stdout.close()  # Allow p2 to receive a SIGPIPE if p3 exits.

output = p3.communicate()[0]

【问题讨论】:

    标签: python subprocess pipe


    【解决方案1】:

    根据https://docs.python.org/2/library/subprocess.html 的python 文档第17.1.4.2 项,在启动p2 之后调用p1.stdout.close() 很重要,以便在p2 在p1 之前退出时p1 接收SIGPIPE。 同样,p2.stdout.close() 也应该在启动 p3 之后调用。

    How to handle a broken pipe (SIGPIPE) in python? 解释了如何处理损坏的管道 (SIGPIPE)。

    【讨论】:

    • 这个答案对于我应该如何解决这个问题不是很清楚。我已经阅读了文档,但我不太清楚,当我调用这些方法时,后台会发生什么。我看到许多可能的解决方案符合文档中提供的指导方针,这就是为什么我正在寻找一个答案(最好是代码示例),它不仅有效,而且不会在以后每隔 2 个星期日出现一个晦涩难懂的错误.
    • 管道用于进程之间的通信。如果 p1 将数据写入 p2 并且 p2 不再存在,则将生成一个符号 SIGPIPE 到 p1 并且 p1 将能够处理这个。 Python 推荐我回答的内容以保证这种行为。
    • 我仍然不清楚您的答案的可操作形式。你是说,如果我有 N 个进程的管道,p1 | p2 | p3 |...| pN,在 python/subprocess 中,我应该将 p1.stdout.close() 放在我喜欢的任何地方,但是在 Popen(p2) 之后?我可以把它放在communicate()之前,communicate()之后,没关系?我什至可以在 p2.stdout.close() 之前调用 p3.stdout.close(),可以吗?您使用哪个展示位置?
    • 您提出了两种选择。我会用第一个。我是 Python 新手。我体验过用 C 编程进程和管道。如果你知道 Python 中的进程,也许你可以创建两个进程 p1 和 p2。 p1 循环通过管道将数据写入 p2。 p2 从 p1 读取数据。在定时器 p2 设置的时间后退出。 p1 会尝试向 p2 发送数据,而 p2 将无法接收。应该像 SIGPIPE 一样引发异常。
    猜你喜欢
    • 1970-01-01
    • 2021-05-19
    • 1970-01-01
    • 1970-01-01
    • 2020-01-18
    • 2014-07-19
    • 1970-01-01
    • 2012-03-21
    • 2018-12-10
    相关资源
    最近更新 更多