【问题标题】:redirecting shell output using subprocess使用子进程重定向 shell 输出
【发布时间】:2011-07-03 02:39:39
【问题描述】:

我有一个调用很多 shell 函数的 python 脚本。该脚本可以从终端以交互方式运行,在这种情况下我想立即显示输出,或者由 crontab 调用,在这种情况下我想通过电子邮件发送错误输出。

我写了一个辅助函数来调用shell函数:

import subprocess
import shlex
import sys

def shell(cmdline, interactive=True):
    args = shlex.split(cmdline.encode("ascii"))
    proc = subprocess.Popen(args, stdout=subprocess.PIPE,
        stderr=subprocess.PIPE)
    val = proc.communicate()
    if interactive is True:
        if proc.returncode:
            print "returncode " + str(proc.returncode)
            print val[1]
            sys.exit(1)
        else:
            print val[0]
    else:
        if proc.returncode:
            print ""
            # send email with val[0] + val[1]

if __name__ == "__main__":
    # example of command that produces non-zero returncode
    shell("ls -z")

我遇到的问题有两个。

1) 在交互模式下,当 shell 命令需要一段时间才能完成时(例如几分钟),在命令完全完成之前我什么都看不到,因为communicate() 缓冲了输出。有没有办法在输入时显示输出并避免缓冲?我还需要一种方法来检查返回码,这就是我使用communicate() 的原因。

2) 我调用的一些 shell 命令会产生大量输出(例如 2MB)。 communicate() 的documentation 表示“如果数据量很大或不受限制,请不要使用此方法”。有谁知道“大”有多大?

【问题讨论】:

    标签: python linux subprocess


    【解决方案1】:

    1) 当您使用 communicate 时,您会捕获子进程的输出,因此不会将任何内容发送到您的标准输出。子流程完成后您看到输出的唯一原因是您自己打印。

    由于您想在运行时查看它而不捕获它,或者只在最后捕获所有内容并对其进行处理,您可以通过离开 stdout 来更改它在交互模式下的工作方式和 stderrNone。这使得子进程使用与您的程序相同的流。您还必须将对 communicate 的调用替换为对 wait 的调用:

    if interactive is True:
        proc = subprocess.Popen(args)
        proc.wait()
        if proc.returncode:
            print "returncode " + str(proc.returncode)
            sys.exit(1)
    else:
        proc = subprocess.Popen(args, stdout=subprocess.PIPE,
            stderr=subprocess.PIPE)
        val = proc.communicate()
        if proc.returncode:
            print ""
            # send email with val[0] + val[1]
    

    2)太大是“太大而无法存储在内存中”,所以这取决于很多因素。如果在您的情况下暂时在内存中存储 2MB 的数据就可以了,那么就没有什么好担心的了。

    【讨论】:

      猜你喜欢
      • 2023-03-06
      • 2021-03-25
      • 1970-01-01
      • 2016-03-28
      • 2011-11-16
      • 1970-01-01
      • 2013-06-02
      • 1970-01-01
      相关资源
      最近更新 更多