简体   繁体   English

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

[英]How to get exit status using subprocess in python?

I have to run a "commit" command through python script and print a message based on its exit or return status. 我必须通过python脚本运行“提交”命令,并根据其退出或返回状态打印一条消息。

code is as follows: 代码如下:

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'

This is giving me following error: 这给了我以下错误:

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

how to correct this error? 如何纠正这个错误?

From the docs; 从文档;

args should be a sequence of program arguments or else a single string. args应该是程序参数的序列,或者是单个字符串。 By default, the program to execute is the first item in args if args is a sequence. 默认情况下,如果args是序列,则要执行的程序是args中的第一项。 If args is a string, the interpretation is platform-dependent and described below. 如果args是字符串,则解释取决于平台,并在下面进行描述。 See the shell and executable arguments for additional differences from the default behavior. 有关默认行为的其他区别,请参见shell和可执行参数。 Unless otherwise stated, it is recommended to pass args as a sequence. 除非另有说明,否则建议将args作为序列传递。

On Unix, if args is a string, the string is interpreted as the name or path of the program to execute. 在Unix上,如果args是字符串,则将该字符串解释为要执行的程序的名称或路径。 However, this can only be done if not passing arguments to the program. 但是,只有在不将参数传递给程序的情况下才能执行此操作。

So, it's looking for a file hg commit -m "{}" and the .format(msg) . 因此,它正在寻找文件hg commit -m "{}".format(msg) Popen wants a list, the fist element being "hg", or better, a real path. Popen想要一个列表,第一个元素是“ hg”,或者更好的是真实路径。

Or set shell=True in Popen (this all from the docs, not pretending to actually test this very often) and get a Popen(['/bin/sh', '-c', args[0], args[1], ...]) effect. 或在Popen中设置shell = True (全部来自文档,不假装实际上经常进行测试)并获得Popen(['/bin/sh', '-c', args[0], args[1], ...])效果。

Bakuriu's comment advice is a nice safe bet though, use shlex. Bakuriu的评论建议是一个不错的选择,但请使用shlex。

The aforesaid process is much safer to use... but alternatively there would be dirty ways to do any thing... 前述过程使用起来更安全...但是另外,会有肮脏的方式来做任何事情...

Instead of splitting the command into an array of strings... you can also use shell=True along with stdout = subprocess.PIPE. 除了将命令拆分为字符串数组之外,您还可以将shell=Truestdout = subprocess.PIPE.一起使用stdout = subprocess.PIPE.

But this is what python says about using shell = True. 但这就是python关于使用shell = True.说法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.

If you are not using shell = True and giving a command in a string, it throws the above error you got because the first command it looks for is the shell path and the you passed hg which is not existing. 如果您未使用shell = True并在字符串中给出命令,则会抛出上述错误,因为它查找的第一个命令是shell路径,而您传递的hg不存在。
But use shell = True wisely. 但是明智地使用shell = True

PS Be aware that you have been warned :P PS请注意,您已被警告:P

You are not using shell=True , in which case you need to pass in the command and its arguments preparsed, as a list: 您没有使用shell=True ,在这种情况下,您需要将命令及其准备好的参数作为列表传递:

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

This also means you don't need to quote the message; 这也意味着您无需引用该消息。 that's only needed when using a shell and you want to pass in the whole message as one argument. 仅在使用外壳程序并且您要将整个消息作为一个参数传递时才需要。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM