如何在python中使用子进程获取退出状态?

时间:2014-01-10 08:55:42

标签: python python-2.7

我必须通过python脚本运行“commit”命令,并根据其退出或返回状态打印一条消息。

代码如下:

import subprocess

msg = 'summary about commit'
commitCommand = 'hg commit -m "{}"'.format(msg)

p = subprocess.Popen(commitCommand, stdout=subprocess.PIPE)
output = p.communicate()[0]

if p.returncode:
    print 'commit failed'
    sys.exit()
else:
    print 'Commit done'

这给了我以下错误:

Traceback (most recent call last):
  File "script.py", line 66, in <module>
    p = subprocess.Popen(commitCommand, stdout=subprocess.PIPE)
  File "/usr/lib/python2.7/subprocess.py", line 711, in __init__
    errread, errwrite)
  File "/usr/lib/python2.7/subprocess.py", line 1308, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory

如何更正此错误?

3 个答案:

答案 0 :(得分:0)

来自文档;

  

args应该是一系列程序参数或者是一个单独的字符串。默认情况下,如果args是序列,则要执行的程序是args中的第一项。如果args是一个字符串,则解释与平台有关,如下所述。有关与默认行为的其他差异,请参阅shell和可执行参数。除非另有说明,否则建议将args作为序列传递。

     

在Unix上,如果args是一个字符串,则该字符串被解释为要执行的程序的名称或路径。但是,只有在不将参数传递给程序时才能执行此操作。

因此,它正在寻找文件hg commit -m "{}".format(msg)。 Popen想要一个列表,第一个元素是“hg”,或者更好,一个真正的路径。

或者在Popen 中设置shell = True(这全部来自文档,而不是假装经常对此进行实际测试) 并获得Popen(['/bin/sh', '-c', args[0], args[1], ...])效果。

Bakuriu的评论建议是一个不错的安全赌注,但使用shlex。

答案 1 :(得分:0)

上述过程使用起来更安全......但是也可能有肮脏的方法做任何事情......

您可以将shell=Truestdout = subprocess.PIPE.

一起使用,而不是将命令拆分为字符串数组...

但这就是python关于使用shell = True.

的说法
Warning Passing shell=True can be a security hazard if combined with untrusted input. See the warning under Frequently Used Arguments for details.

如果你没有使用shell = True并在字符串中给出一个命令,它会抛出你得到的上述错误,因为它查找的第一个命令是shell路径,而你传递的hg是不存在的。
但明智地使用shell = True

P.S。请注意,您已收到警告:P

答案 2 :(得分:0)

您没有使用shell=True,在这种情况下,您需要传递命令及其参数,并将其作为列表传递:

commitCommand = ['hg', 'commit', '-m', msg]

这也意味着您不需要引用消息;只有在使用shell时才需要,并且您希望将整个消息作为一个参数传递。