在线阅读一些程序员使用sys.exit
,其他程序员使用SystemExit
对不起基本问题:
实施例
ref = osgeo.ogr.Open(reference)
if ref is None:
raise SystemExit('Unable to open %s' % reference)
或
ref = osgeo.ogr.Open(reference)
if ref is None:
print('Unable to open %s' % reference)
sys.exit(-1)
答案 0 :(得分:24)
sys.exit(s)
只是raise SystemExit(s)
的简写,如前者的文档字符串所述;试试help(sys.exit)
。因此,您可以执行
sys.exit('Unable to open %s' % reference)
答案 1 :(得分:21)
没有实际区别,但是你的示例代码有另一个区别 - print
转到标准输出,但异常文本转到标准错误(这可能是你想要的)。
答案 2 :(得分:10)
除了提出SystemExit
之外,还有3个退出功能。
底层的是os._exit
,它需要1个int参数,并且在没有清理的情况下立即退出。你不太可能想触摸这个,但它就在那里。
sys.exit
在sysmodule.c中定义,只运行PyErr_SetObject(PyExc_SystemExit, exit_code);
,实际上与直接引发SystemExit
相同。详细而言,提升SystemExit
可能会更快,因为sys.exit
需要LOAD_ATTR
和CALL_FUNCTION
与RAISE_VARARGS
操作号。此外,raise SystemExit
产生的字节码略小(减少4字节),(如果使用from sys import exit
则额外增加1个字节,因为sys.exit
预计会返回None,因此包含额外的POP_TOP
) 。
最后一个退出函数在site.py
中定义,在REPL中别名为exit
或quit
。它实际上是Quitter
类的一个实例(因此它可以有自定义__repr__
,因此可能是最慢的运行。此外,它在提升sys.stdin
之前关闭SystemExit
,因此建议仅在REPL中使用。
至于如何处理SystemExit
,最终会导致VM调用os._exit,但在此之前,它会进行一些清理。它还运行atexit._run_exitfuncs()
,运行通过atexit
模块注册的任何回调。直接拨打os._exit
会绕过atexit
步骤。
答案 3 :(得分:6)
我个人的偏好是至少提出SystemExit
(或者更好 - 一个更有意义且记录良好的自定义异常),然后尽可能接近“主要”功能,然后可以有最后的机会认为它是一个有效的退出。从设计的角度来看,具有sys.exit
的库/深度嵌入的函数简直令人讨厌。 (一般来说,退出应该“尽可能高”)
答案 4 :(得分:3)
SystemExit
是一个例外,这基本上意味着你的程序有一个行为,你想要阻止它并引发错误。 sys.exit
是您可以调用以退出程序的函数,可能会向系统返回代码。
答案 5 :(得分:2)
根据文档sys.exit(s)
有效地raise SystemExit(s)
,所以它几乎是一样的。
答案 6 :(得分:0)
尽管许多答案都回答了这种差异,但https://mail.python.org/pipermail/python-list/2016-April/707470.html提出了一个有趣的观点:
TL; DR:最好只提出一个正常的"异常,并且仅在脚本的顶级使用SystemExit
或sys.exit
。
我在python 2.7和Linux上,如果我有一个简单的代码需要建议 我可以用raise SystemExit替换sys.exit(1)。
==实际代码==
def main(): try: create_logdir() create_dataset() unittest.main() except Exception as e: logging.exception(e) sys.exit(EXIT_STATUS_ERROR) if __name__ == '__main__': main()
==更改了代码==
def main(): try: create_logdir() create_dataset() unittest.main() except Exception as e: logging.exception(e) raise SystemExit if __name__ == '__main__': main()
我个人反对这两个人。我喜欢的模式是这样的 这样:
def main(argv): try: ... except Exception as e: logging.exception(e) return 1 if __name__ == '__main__': sys.exit(main(sys.argv))
请注意,main()恢复为正常的正常函数 回报。
此外,我们大多数人都会避免"除了异常"然后让一个顶部 除了冒出来之外的水平:这样你得到一个堆栈回溯 调试。我同意它可以防止记录异常并实现 更丑陋的控制台输出,但我认为这是一场胜利。如果你做想要 记录异常总是这样:
尝试: ...除了例外的e: logging.exception(e)中 提高
将异常列入日志并仍然让它冒出来 通常
除了例外""模式是它捕捉和 皮 每个例外,而不仅仅是您理解的一组特定的例外情况。
最后,提出一个裸露的Exception类是不受欢迎的。在 python 3我相信它实际上是被禁止的,所以它是不可移植的 无论如何。但即使在Python中也最好提供Exception 例如,不是班级:
提升SystemExit(1)
- 醇>
try块中的所有函数都使用raise
冒出异常create_logdir()的示例这里是函数定义
def create_logdir():
尝试: os.makedirs(LOG_DIR) 除了OSError为e: sys.stderr.write("无法创建日志目录...退出!!!") 提高 打印"日志文件:" + corrupt_log 返回True
def main(): 尝试: create_logdir() 除了例外e: logging.exception(e)中 提升SystemExit
(a)如果create_logdir()失败,我们将得到以下错误,是 这很好,还是我需要改进这段代码。
创建日志目录失败...退出!!!错误:root:[Errno 17]文件 存在:' / var / log / dummy'
追踪(最近一次通话): 文件" corrupt_test.py",第245行,在main中 create_logdir() 在create_logdir中输入文件" corrupt_test.py",第53行 os.makedirs(LOG_DIR) 文件" /usr/local/lib/python2.7/os.py" ;,第157行,在makedirs中 OSError:[Errno 17]文件存在:' / var / log / dummy'
我更喜欢冒泡的方法,记录日志或警告 你已经做过的消息,例如:
logging.exception(" create_logdir失败:makedirs(%r):%s"% (LOG_DIR,e))提高
(也不是说该日志消息记录了更多上下文:context非常 在调试问题时很有用。)
对于非常小的脚本,sys.stderr.write是可以的,但通常是任何一个 结果通常有用的功能可能会迁移 进入图书馆以便重复使用;认为stderr不是 永远是消息的地方;而是读取记录模块 适当时使用error()或wanr()或exception()。还有更多 在没有布线的情况下配置输出的方式的范围 它进入你的内在功能。
- 醇>
我可以加注,而不是SystemExit或sys.exit(1)。这个 看起来不对我
def main():
尝试: create_logdir() 除了例外的e logging.exception(e)中 提高
这就是我自己要做的事。
思考:有例外情况"处理",意味着有这种情况 因为预期会被处理?如果没有,请让例外 冒泡,以便用户知道不所理解的东西 该计划已经发生。
最后,从内部对SystemExit或sys.exit()通常不好 除最外面的main()函数以外的任何东西。我抵制它 即使在那里;如果写得好,主要功能可能经常被调用 从其他地方有用,这使它成为一个有效的库 功能(已被重用)。这样的功能不应该 单方面中止该计划。太粗鲁了!相反,让异常 冒泡:也许main()的调用者需要它并且可以处理 它。通过中止而不是“提升”,你已经剥夺了来电者 即使你自己,也有机会做一些合适的事情 (即" main")不知道足够的上下文来处理异常。
所以我是为了#34;加注"我。然后只是因为你想记录 错误。如果你不想记录异常,你可以避免 尝试/除了完全并且代码更简单:让来电者担心 关于未处理的例外情况!