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

很抱歉问了一个基本问题:

  • 有什么区别
  • 何时需要在函数中使用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('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函数
    vs
    RAISE\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))