大多数pythonic方式从shell命令获取输出

时间:2014-07-25 08:42:12

标签: python subprocess stdout python-2.x

我正在编写我的第一个python程序,我想运行一个shell命令并获取输出。我想以最干净/最pythonic的方式做到这一点。这就是我所拥有的。 注意:我还想在执行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)(< = ls命令没有' t需要4秒钟才能完成),返回码为None,这意味着子进程尚未完成。这怎么可能? 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 <​​/ strong>,但我不确定如何用Popen调用它,任何人都可以帮忙吗?

2 个答案:

答案 0 :(得分:3)

是的,communicate暗示wait;它会在关闭过程中读取流程“stdoutstderr

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


对于一种非常pythonic的方式来轻松获取命令的输出,请参阅自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
)

但是,您也可以Popen使用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()

答案 1 :(得分:1)

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

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

如果您不致电process.communicate(),那么process.returncode的默认值为None以及将process.communicate()替换为time.sleep(4)时的返回值。

Popen.returncode

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

负值-N表示孩子被信号N终止(仅限Unix)。