【问题标题】:Is there a quiet version of subprocess.call?是否有 subprocess.call 的安静版本?
【发布时间】:2012-01-21 16:44:57
【问题描述】:

是否有subprocess.call 的变体可以在不打印到标准输出的情况下运行命令,或者有一种方法可以阻止它的标准输出消息?

【问题讨论】:

标签: python subprocess silent


【解决方案1】:

是的。将其stdout 重定向到/dev/null

process = subprocess.call(["my", "command"], stdout=open(os.devnull, 'wb'))

【讨论】:

    【解决方案2】:

    stderr 上经常会出现这种喋喋不休的声音,因此您可能也希望将其静音。从 Python 3.3 开始,subprocess.call 直接有这个特性:

    要禁止 stdout 或 stderr,请提供值 DEVNULL

    用法:

    import subprocess
    rc = subprocess.call(args, stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)
    

    如果你还在使用 Python 2:

    import os, subprocess
    
    with open(os.devnull, 'wb') as shutup:
        rc = subprocess.call(args, stdout=shutup, stderr=shutup)
    

    【讨论】:

    • 注意到使用startupinfo 没有答案,如下所示:code.activestate.com/recipes/… 以避免在从控制台运行 python 时窗口闪烁
    • @Jean-FrançoisFabre 我从来没有听说过。可能是特定于 Windows 的东西?
    • 可能是的。如果你想在窗户上对抗癫痫,那是必须的。
    【解决方案3】:

    这是我经常使用的配方:调用subprocess 并收集输出,当命令成功时丢弃输出,但当失败时打印输出。

    import subprocess as sp
    import sys
    
    if "print" in __builtins__.__dict__:
        prn = __builtins__.__dict__["print"]
    else:
        def prn(*args, **kwargs):
            """
            prn(value, ..., sep=' ', end='\\n', file=sys.stdout)
            Works just like the print function in Python 3.x but can be used in 2.x.
    
            Prints the values to a stream, or to sys.stdout by default.
            Optional keyword arguments:
            file: a file-like object (stream); defaults to the current sys.stdout.
            sep:  string inserted between values, default a space.
            end:  string appended after the last value, default a newline.
            """
            sep = kwargs.get("sep", ' ')
            end = kwargs.get("end", '\n')
            file = kwargs.get("file", sys.stdout)
    
            s = sep.join(str(x) for x in args) + end
            file.write(s)
    
    
    def rc_run_cmd_basic(lst_cmd, verbose=False, silent=False):
        if silent and verbose:
            raise ValueError("cannot specify both verbose and silent as true")
    
        p = sp.Popen(lst_cmd, stdin=sp.PIPE, stdout=sp.PIPE, stderr=sp.PIPE)
        tup_output = p.communicate()
    
        s_cmd = ' '.join(lst_cmd)
        if verbose:
            prn()
            prn("command: '%s'\n" % s_cmd)
    
            if 0 != p.returncode:
                prn()
                prn("Command failed with code %d:" % p.returncode)
            else:
                prn("Command succeeded!  code %d" % p.returncode)
        if verbose:
            prn("Output for: " + s_cmd)
            prn(tup_output[0])
            prn()
        if not silent and 0 != p.returncode:
            prn("Error output for: " + s_cmd)
            prn(tup_output[1])
            prn()
    
        return p.returncode
    

    【讨论】:

    • 这是对 subprocess 中已有功能的(糟糕的)改造。处理CalledProcessError 更容易,它已经具有捕获的stdout 和stderr 的属性。
    【解决方案4】:

    我在这种情况下使用 subprocess.check_output 并删除返回值。您可能需要在代码中添加注释,说明您使用 check_output 代替 check_call 的原因。当发生故障并且您对错误输出感兴趣时, check_output 也更好。下面的示例代码。仅当您取消注释打印行时才能看到输出。如果命令失败,则抛出异常。

    import subprocess
    ret = subprocess.check_output(["cat", "/tmp/1"])
    #print ret
    

    【讨论】:

    • 删除返回值如何防止输出到标准输出?
    • subprocess.check_output 应该捕获输出并返回它。您是否看到了不同的行为?
    • 捕获和忽略工作,但在捕获的值上浪费内存,然后永远不会使用。正确丢弃输出更健壮。
    • 我同意会浪费内存。但是对于只输出几个字节的小命令,它是可以的。取决于您的用例。更好的解决方案是按照接受的解决方案中的建议重定向到 /dev/null。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-06
    • 1970-01-01
    • 1970-01-01
    • 2011-10-18
    相关资源
    最近更新 更多