关于python:从shell命令获取输出的大多数python方法

Most pythonic way to get output from a shell command

本问题已经有最佳答案,请猛点这里访问。

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

1
2
3
4
5
6
7
8
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.communication(),并将其替换为time.sleep(4)(<=ls命令不需要4秒钟完成),返回代码为none,这意味着子进程还没有建立。这怎么可能?out,err=process.communication()是否执行隐式wait()方法调用?

1
2
3
4
5
6
7
8
9
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,有人能帮我吗?


是的,communicate表示wait;它读取进程"stdout"和stderr,直到它们关闭。

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

要获得命令输出的一种非常简单的方法,请参见从python 3.1和2.7开始提供的popen.check_输出,尽管它不会在失败时引发stderr的内容异常。如果需要将stderr的内容作为消息包含在异常中,那么第一个示例是好的。

要在python中调用完整管道,可以使用shell=True和完整管道作为命令。

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

但是,您也可以使用Popens制作管道:

1
2
3
4
5
6
7
8
9
10
11
12
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()


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

当您调用process.communicate()时,它将实际调用command并在process.returncode中设置值。

如果您不调用process.communicate(),那么process.returncode的缺省值为None,当您用time.sleep(4)替换process.communicate()时,它的返回值是多少。

Popen.Return代码

子返回代码,由poll()和wait()设置(并由communication()间接设置)。无值表示进程尚未终止。

负值-n表示子级被信号n终止(仅限于Unix)。