【问题标题】:How to capture output of subprocess OTHER than stdout/stderr?如何捕获子进程的输出而不是标准输出/标准错误?
【发布时间】:2012-09-17 08:27:25
【问题描述】:

我有一个想通过子进程启动的程序。它可以输出到除 stdout 和 stderr 以外的 fd。有没有办法从任意 fd 捕获数据?如果我的进程将输出发送到 fd 9,我想做类似以下的事情:

import subprocess, StringIO
redirector = StringIO.StringIO()
errno = subprocess.call(cmd, fd9=redirector)
#process the error code and data in redirector

我确实想通过 stderr 或 stdout 将被调用进程的输出重定向到 fd 9。

【问题讨论】:

    标签: python subprocess


    【解决方案1】:

    如果程序在开始运行后打开文件描述符 9(或其他),那么就没有办法做你想做的事。

    如果程序没有打开文件描述符 9 本身,而是从父进程中获取它,那么您可以使用 preexec_fn 参数为 subprocess.Popen 做你想做的事,但它是不像为StringIO 实例设置一些东西那么简单。您必须手动创建一个管道,并且您必须安排及时读取它,否则您导致死锁。期望编写两三百行代码才能做到 100% 正确。我不会在这里放任何示例代码,因为我不想让它看起来比实际更容易。

    除了subprocess.Popen,您还需要os.pipeos.dup2os.read,并且您需要了解底层系统原语: pipe(2)dup2(2)read(2)fork(2)execve(2)

    现在可能是投资Advanced Programming in the Unix Environment 副本的好时机。

    【讨论】:

    • 呃,谢谢。该程序确实确实打开了文件描述符 9(或其他)本身。听起来我需要寻找另一种解决方案...
    • 你能控制程序写入的文件名吗,例如使用命令行选项?如果是这样,阻力最小的路径可能是让它写入临时目录(tempfile.mkdtemp)中的文件,然后在子进程完成后正常读取文件的内容。之后可以使用shutil.rmtree进行清理。
    • 糟糕 - 我正在建议使用 close_fds=false 的 subprocess.Popen()。如果父级没有打开 fd9 并且读/写同一个文件与通过管道流式传输不同,那显然是行不通的。
    • @Zach。我当然可以将输出发送到文件。我问这个问题是因为我认为我在 subprocess 模块中遗漏了一些非常可爱的东西。好像没有。
    • 不幸的是,不,你没有错过任何东西。您可以从父级到子级继承您喜欢的任何文件描述符,但如果它自己打开文件,则不能从另一个进程下窃取文件。
    猜你喜欢
    • 2010-10-29
    • 1970-01-01
    • 2013-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-18
    • 1970-01-01
    相关资源
    最近更新 更多