Python:使用sys.exit或SystemExit差异和建议
在线阅读一些程序员使用Python:使用sys.exit或SystemExit差异和建议,python,performance,coding-style,Python,Performance,Coding Style,在线阅读一些程序员使用sys.exit,其他程序员使用SystemExit 很抱歉问了一个基本问题: 有什么区别 何时需要在函数中使用SystemExit或sys.exit 范例 ref = osgeo.ogr.Open(reference) if ref is None: raise SystemExit('Unable to open %s' % reference) 或 sys.exit(s)只是raisesystemexit(s)的简写,如前者的docstring中所述;尝试帮
sys.exit
,其他程序员使用SystemExit
很抱歉问了一个基本问题:
ref = osgeo.ogr.Open(reference)
if ref is None:
raise SystemExit('Unable to open %s' % reference)
或
sys.exit(s)
只是raisesystemexit(s)
的简写,如前者的docstring中所述;尝试帮助(系统退出)
。因此,您可以不使用任何一个示例程序
sys.exit('Unable to open %s' % reference)
根据文档
sys.exit(s)
实际上是引发系统退出
,所以这几乎是一样的。SystemExit
是一个例外,这基本上意味着您的程序有一种行为,您希望停止它并引发错误sys.exit
是您可以调用以退出程序的函数,可能会向系统提供返回代码
编辑:它们确实是相同的东西,所以唯一的区别在于程序背后的逻辑。异常是一种“不想要的”行为,无论从程序员的角度来看,对函数的调用是否更像是一种“标准”操作。我个人的偏好是,至少会引发
SystemExit
(或者更好——一种更有意义、文档更完善的自定义异常),然后捕获到与“main”尽可能接近的异常尽可能地发挥作用,然后才有最后一次机会将其视为有效退出或无效退出。从设计的角度来看,具有sys.exit
的库/深度嵌入函数非常讨厌。(通常,退出应该尽可能“高”。没有实际的区别,但是示例代码中还有另一个区别-打印
转到标准输出,但异常文本转到标准错误(这可能是您想要的)。除了引发系统退出
之外,还有3个退出函数
底层的是os.\u exit
,它需要1个int参数,并立即退出而不进行清理。你不太可能想要碰这个,但它就在那里
sys.exit
在sysmodule.c中定义,只运行PyErr\u SetObject(PyExc\u SystemExit,exit\u code)
,这实际上与直接引发SystemExit
相同。具体来说,提升SystemExit
可能更快,因为sys.exit
需要一个LOAD\u ATTR
和CALL\u函数
vsRAISE\u VARARGS
opcalls。另外,raise SystemExit
生成的字节码稍小(少4个字节),(如果从sys import exit使用,则额外增加1个字节,因为sys.exit
预计不返回任何字节,因此包含一个额外的POP\u TOP
)
最后一个退出功能在site.py
中定义,并在REPL中别名为exit
或quit
。它实际上是Quitter
类的一个实例(因此它可以有一个自定义的\uu repr\uu
,因此可能是运行最慢的。此外,它在引发SystemExit
之前关闭sys.stdin
,因此建议仅在REPL中使用
至于如何处理SystemExit
,它最终会导致VM调用os.\u exit,但在此之前,它会进行一些清理。它还运行atexit.\u run\u exitfuncs()
运行通过atexit
模块注册的任何回调。调用os.\u exit
直接绕过atexit
步骤。虽然有许多答案回答了这一差异,但有一点很有趣:
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()
我个人反对这两种模式。我喜欢的模式是
这:
请注意,main()已恢复为具有normal的normal函数
返回
此外,我们大多数人都会避免“例外情况除外”,只让顶部
除气泡外的标高:这样您可以获得
调试。我同意它可以防止记录异常,并使
更丑陋的控制台输出,但我认为这是一个胜利。如果你想
要记录异常,始终存在以下情况:
尝试:
…例外情况除外,如e:
logging.exception(e)
提高
将异常记录在日志中,并让它冒泡出来
通常
“Exception Exception”模式的问题是它捕获并
兽皮
每一个异常,而不仅仅是你所理解的一组狭隘的特定异常
最后,不赞成提出一个简单的异常类
python 3我认为它实际上是被禁止的,所以它是不可移植的
无论如何,但即使在Python中,也最好提供一个异常
实例,而不是类:
升起系统出口(1)
try块中的所有函数都使用raise弹出异常
create_logdir()的示例这里是函数定义
def create_logdir():
尝试:
os.makedirs(LOG\u DIR)
除O错误为e外:
sys.stderr.write(“未能创建日志目录…正在退出!!!”)
提升
打印“日志文件:”+损坏的日志
返回真值
def main():
尝试:
创建_logdir()
例外情况除外,如e:
logging.exception(e)
升起系统出口
(a) 如果create_logdir()失败,我们将得到以下错误,即
这很好,或者我需要改进这段代码
无法创建日志目录…正在退出!!!错误:根:[Er]
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))