加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

如何使用Python调用命令,捕获stderr和stdout,而无需等待stderr /

发布时间:2020-12-20 13:39:43 所属栏目:Python 来源:网络整理
导读:现在我有一些代码使用来自子进程的 Popen.communicate() (设置stdin = PIPE和stderr = PIPE)来运行命令并捕获stderr和stdout. 问题是communication()不仅等待命令退出,还等待stdout和stderr关闭.我正在运行的命令会生成一个子进程,它会使stderr保持打开状态,
现在我有一些代码使用来自子进程的 Popen.communicate()(设置stdin = PIPE和stderr = PIPE)来运行命令并捕获stderr和stdout.

问题是communication()不仅等待命令退出,还等待stdout和stderr关闭.我正在运行的命令会生成一个子进程,它会使stderr保持打开状态,所以即使命令运行完毕(并在ps中显示为“defunct”),仍然会挂起().

我想只等待命令完成而不等待stderr / stdout.但我仍然希望捕获命令运行时给出的任何stderr / stdout输出. The documentation for wait()附有一个带免责声明的红色方框:

This will deadlock when using stdout=PIPE and/or stderr=PIPE and the child process generates enough output to a pipe such that it blocks waiting for the OS pipe buffer to accept more data. Use communicate() to avoid that.

显然,我也想避免陷入僵局.

完成这项任务的正确方法是什么?

解决方法

“在ps中显示为”defunct“意味着您可能在select或fcntl可以工作的系统上,即,您可以轻松地读取stdout / stderr.

示例:A启动B(cmd,孩子),B启动C(孙子),A读取输出直到B退出或EOF:

#!/usr/bin/env python
import os
from select import select
from subprocess import Popen,PIPE

p = Popen(cmd,stdout=PIPE,stderr=PIPE,bufsize=0)
read_set = [p.stdout,p.stderr]
pipename = {p.stdout: "stdout",p.stderr: "stderr"}
timeout = 0.5 # ugly but it works
while read_set and p.poll() is None: # while subprocess is running or until EOF
    for pipe in select(read_set,[],timeout)[0]:
        data = os.read(pipe.fileno(),1<<30)
        if data:
            print("got from %s: %r" % (pipename[pipe],data))
        else: # EOF
            pipe.close()
            read_set.remove(pipe)
print("exit code %s" % (p.wait(),))

# child exited,wait for grandchild to print
for pipe in read_set:
    print("read the rest of %s: %r" % (pipename[pipe],pipe.read()))
    pipe.close()

其中cmd:

import sys
from textwrap import dedent

cmd = [sys.executable,'-u','-c',dedent("""
    # inception style
    import os
    import sys
    from subprocess import Popen
    from textwrap import dedent

    Popen([sys.executable,dedent('''
        import os
        import sys
        import time

        time.sleep(60)
        print("grandchild %d done" % os.getpid())
        sys.stderr.write("grandchild stderr")
        sys.exit(20)
    ''')]) # stdout/stderr are not redirected

    print('child %d done' % os.getpid())
    sys.stderr.write('child stderr')
    sys.exit(19)
""")]

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读