【问题标题】:Most pythonic way to get output from a shell command [duplicate]从shell命令获取输出的最pythonic方式[重复]
【发布时间】:2014-07-25 08:42:11
【问题描述】:

我正在编写我的第一个 python 程序,我想运行一个 shell 命令并获取输出。我想以最干净/最pythonic的方式来做。这就是我的atm。 注意:我还想在执行 shell 命令时出现异常时引发异常。

def lsCommand():
    process = subprocess.Popen(['ls', '-a'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    out , err = process.communicate()
    returnc = process.returncode
    if returnc != 0:
        raise Exception(err)
    else:
        return out

我发现,当我删除 out , err = process.communicate() 行并将其替换为 time.sleep(4) 时(out , err = process.communicate() 是否执行隐式 wait() 方法调用?

def lsCommand():
    process = subprocess.Popen(['ls', '-a'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    time.sleep(4)
    returnc = process.returncode
    if returnc != 0:
        print returnc
        raise Exception(err)
    else:
        return out

编辑:我使用的是 python 2.7

我想做一个更长的命令 sudo find "/media/usb0" -type f -name "*.JPG" | wc -l,但我不知道如何用 Popen 调用它,有人可以帮忙吗?

【问题讨论】:

    标签: python subprocess stdout python-2.x


    【解决方案1】:

    是的,communicate 暗示 wait;它会读取进程'stdoutstderr,直到它们被关闭。

    在第二个例子中你PIPEls的输出;子进程ls 被阻止写入stdoutstderr,直到您从管道中读取 - 因此它不会在 4 秒内完成,甚至在读取这些描述符之前甚至 4 年内都不会完成。但是,由于手动轮询描述符容易出错,Popen 类有 communicate 方法来避免这些陷阱。


    有关轻松获取命令输出的非常 Python 的方法,请参阅自 Python 3.1 和 2.7 起可用的Popen.check_output,尽管它不会在失败时引发stderr 内容的异常。如果您需要异常以包含 stderr 的内容作为消息,则您的第一个示例很好。


    要在 Python 中调用完整管道,您可以将 shell=True 与完整管道一起用作命令。

    pipeline = subprocess.Popen(
        'sudo find "/media/usb0" -type f -name "*.JPG" | wc -l',
        shell=True,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE
    )
    

    不过,你也可以使用Popens 到make the pipeline

    find = subprocess.Popen(
        ['sudo', 'find', '/media/usb0', '-type', 'f', '-name', '*.JPG'],
        stdout=subprocess.PIPE
    )
    wc = subprocess.Popen(
        ['wc', '-l'],
        stdin=find.stdout,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE
    )
    find.stdout.close()
    wc.communicate()
    

    【讨论】:

    • 我使用的是 python 2.7,应该这么说。对不起。我将编辑我的问题
    • 我已经阅读了关于 check_output 的信息,我尝试使用它但它不起作用,将再试一次。谢谢。您是否碰巧知道如何在我的第一篇文章中使用更长的命令(如 sudo find ...)?
    • 如果我不关心错误消息,这是否更 Pythonic?:def lsCommand(): process = subprocess.check_output(['ls','-l']) return process跨度>
    • 据我了解,您在帖子末尾给出的 find 示例无法使用 check_output 方法完成,因为您使用的是 stdout=subprocess.PIPE ,这可能会导致死锁文档。我说的对吗?
    • 啊,你wc.communicate()
    【解决方案2】:

    它不会调用time.sleep,它会等到命令执行完毕,可能需要4秒或更长时间。

    当您调用process.communicate() 时,它实际上会调用命令并设置process.returncode 中的值。

    如果您不调用process.communicate(),则process.returncode 的默认值为None,当您将process.communicate() 替换为time.sleep(4) 时返回的值。

    Popen.returncode

    子返回码,由 poll() 和 wait() 设置(间接通过communicate())。 None 值表示该进程尚未终止。

    负值 -N 表示子进程被信号 N 终止(仅适用于 Unix)。

    【讨论】:

    • 谢谢,很有帮助。
    • 如果它解决了您的问题,请选择它作为答案
    • 它部分解决了这个问题,但我仍然想知道这是否是在 python 2.7 上编写以从 shell 命令获取输出的最干净的代码。或者有什么更干净的方法?
    猜你喜欢
    • 2010-09-12
    • 2021-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-18
    • 1970-01-01
    相关资源
    最近更新 更多