Python中的退出代码

328

我收到一条消息,上面写着 脚本 xyz.py 返回退出码 0。这是什么意思?

在 Python 中,退出码代表什么?有多少种退出码?哪些退出码比较重要?


4
你在哪里看到这条消息? - Jeremy Cantrell
3
在PythonWin的底部。 - sundeep
16个回答

324
你正在寻找脚本中的sys.exit()调用(exit()调用sys.exit())。该方法的参数作为退出代码返回给环境。
很有可能脚本从未调用过exit方法,而默认的退出代码是0。

15
在Unix/Linux中,标准是:如果一切正常,则使用退出代码0。输入一个命令,然后使用echo $?:如果返回值为0,则表示没有错误。这个想法是为了有标准的测试方法。如果代码xyz.py没有遇到任何错误,它应该返回0! - Bruno von Paris
2
如果您想更改退出代码,请优先使用exit内置函数进行干净的退出,参见此答案 - vidstige
@vidstige:exit()“内置”函数(实际上并非总是内置的;例如,当使用-S开关运行Python时,它将不存在)是错误的解决方案;你需要使用sys.exit()(它确实可以干净/一致地退出),而不是exit()(工具可以用奇怪的东西替换它,而sys.exit通常应该保持不变)。"不干净的退出"函数是os._exit(),它会突然终止(主要用于在基于forkmultiprocessing场景中杀死工作进程,以避免调用父进程在fork之前设置的清理操作)。 - ShadowRanger

141

sys.exit的文档中得知:

可选参数arg可以是一个整数来表示退出状态(默认为0)或者其他类型的对象。如果它是一个整数,那么零被认为是“正常终止”,任何非零值则被认为是“异常终止”并且由shell等解释器处理。大多数系统要求它在0-127的范围内,否则会导致未定义的结果。一些系统约定将特定的含义赋给特定的退出代码,但这些通常不完善;Unix程序通常使用2表示命令行语法错误,1表示其他所有错误。

一个使用退出代码的例子是在shell脚本中。在Bash中,您可以检查特殊变量$?以获取上次的退出状态:

me@mini:~$ python -c ""; echo $?
0
me@mini:~$ python -c "import sys; sys.exit(0)"; echo $?
0
me@mini:~$ python -c "import sys; sys.exit(43)"; echo $?
43

个人而言,我尝试使用我在Linux系统上找到的/usr/include/asm-generic/errno.h中的退出代码,但我不知道这是否正确。


4
我找到了另一篇帖子,其中提供了这个链接:http://tldp.org/LDP/abs/html/exitcodes.html ,可能很有用。 :) - Eigir
11
errno.h通常用于函数调用退出代码。试图标准化程序退出代码的尝试导致在大多数POSIX系统上存在了/usr/include/sysexits.h文件。 - mpounsett
2
知道“Unix程序通常使用2来表示命令行语法错误”非常好! - dantiston
4
@ dantiston 赞同。 我是一个死忠的 Gentoo 支持者,但直到今天我才知道这一点……我的耻辱现在结束了。相关地,注意当没有行匹配时 grep 会以 1 退出,而当出现实际错误时则以 2 退出,感谢 Stallman。 - Cecil Curry

52

记录一下,您可以使用在这里定义的POSIX标准退出码。

示例:

import sys, os

try:
    config()
except:
    sys.exit(os.EX_CONFIG) 
try:
    do_stuff()
except:
    sys.exit(os.EX_SOFTWARE)
sys.exit(os.EX_OK) # code 0, all ok

7
根据文档,这些仅适用于Unix操作系统,因此不是完全可移植的。 - phoenix
2
如果您想要在所有操作系统上使用可移植的POSIX代码,请查看exitstatus PyPI软件包。 - phoenix
16
这个“包裹”的全部内容都表示成功为0,失败为1。 - Pavel Minaev
6
我原以为你在开玩笑,Pavel。事实上你并没有在开玩笑: https://github.com/johnthagen/exitstatus/blob/master/exitstatus.py - rud

24

有一个 errno 模块定义了标准退出代码:

例如,权限被拒绝 的错误代码是13

import errno, sys

if can_access_resource():
    do_something()
else:
    sys.exit(errno.EACCES)

47
这是不正确的。这些errno不打算用作进程退出代码。它们是低级错误代码,旨在用于程序内部,特别是那些使用C语言编写的程序。对于Python,请尽可能使用异常。 - SvdB
3
你说得对。这些是用于内部使用的。但通常不会在最终用户级别引发异常。你可以使用sys.exit(x),其中x是任意选择的整数。但你也可以使用以EX_开头并在'os'模块中定义的异常,比如os.EX_OK或os.EX_IOERR。 - Oli
5
很抱歉,我也会给这个帖子点踩,因为它具有误导性。退出状态码和错误号码是不可以互换/相互补充的。以给出的例子为例,“permission denied”在errnoerrno.h中的错误代码是13,但在ossysexits.h中的退出状态码是77。发出前者的程序是非标准的(_de facto vel jure_),并且与正确期望后者的其他程序无法协同工作。 - Mark G.

18

退出代码为0通常表示“没有问题”。但是,如果脚本的程序员没有遵循惯例,您可能需要查看源代码以了解其含义。通常,非零值作为错误代码返回。


14

答案是“取决于零退出代码的含义”。

然而,在大多数情况下,这意味着“一切都好”。


我喜欢 POSIX:

因此,在 shell 中,我会键入:

python script.py && echo 'OK' || echo 'Not OK'

如果我的 Python 脚本调用了 sys.exit(0),则 shell 返回 'OK'。

如果我的 Python 脚本调用了 sys.exit(1)(或任何非零整数),则 shell 返回 'Not OK'。

你需要在 shell 中做些聪明的事情,并查看你的脚本的文档(或源代码)以了解退出代码的含义。


5
为了完整起见,“不OK”将被打印,如果Python脚本引发错误或有语法错误。 - Shital Shah

14

根据Unix退出码0表示成功 / OK,1表示失败 / 错误。你可以直接使用exit(0)exit(1)调用,而无需导入sys模块。


5
exit 用于交互式 shell,sys.exit 用于脚本。另请参阅此答案:https://dev59.com/c2w15IYBdhLWcg3wntAQ#6501134 - highvelcty

8
如果您想要便携地使用标准POSIX退出代码,请查看PyPI上的exitstatus包。
安装该软件包:
$ pip install exitstatus

在你的代码中使用:

import sys
from exitstatus import ExitStatus

sys.exit(ExitStatus.success)

6

退出代码的含义仅由脚本作者指定。Unix传统是,退出代码0表示“成功”,其他任何代码都表示失败。要确定给定脚本的退出代码含义,唯一的方法是检查脚本本身。


6
操作系统命令具有退出代码。查看Linux退出码以了解相关信息。Shell使用退出代码来判断程序是否正常工作、存在问题或失败。目前有一些努力创建标准(或至少常用的)退出代码。请参阅此高级Shell脚本文章。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接