我正在编写我的第一个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调用它,任何人都可以帮忙吗?
答案 0 :(得分:3)
是的,communicate
暗示wait
;它会在关闭过程中读取流程“stdout
和stderr
。
在第二个示例中,您PIPE
输出ls
;在您从管道读取之前,子进程ls
被阻止写入stdout
和stderr
- 因此,在读取这些描述符之前,它不会在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)
时的返回值。
子返回码,由poll()和wait()设置(,间接通过communic())。 “无”值表示该进程尚未终止。
负值-N表示孩子被信号N终止(仅限Unix)。