关于sys.exit和SystemExit的困惑

时间:2014-10-26 19:30:32

标签: python

我已经阅读了SO上的几个主题以及SystemExit异常上的python文档。 这个帖子不是重复的,因为我没有在类似的线程中找到答案。

调用sys.exit()和引发SystemExit都会进行清理吗?我知道sys.exit调用SystemExit,但如果你只是引发SystemExit异常,它会为你做任何清理吗?官方的python doc对此并不十分清楚。我问的原因是因为我的同事认为SystemExit更清楚地写入代码并且您不需要导入sys模块..但只是提出异常我不确定与调用sys相比是否正在进行任何清理.exit在从我所知道的方式调用SystemExit之前进行清理。

3 个答案:

答案 0 :(得分:1)

根据atexit的Python 2文档,似乎sys.exitSystemExit都会导致正常清理。 os._exit不会。

答案 1 :(得分:1)

致电sys.exit()只会引发SystemExit。它是在备份堆栈的过程中完成的异常处理,因此两种技术都会执行相同的清理工作。但是你应该使用sys.exit而不是SystemExit:尽管如此,没有必要尝试保存一个sys的导入,这并不需要花费任何成本。调用sys.exit是结束Python过程的传统方法。

那就是说,您确定要在代码中明确退出流程吗?这使您的功能很难重复使用。通常,当简单地从函数返回时,人们会使用sys.exit,因为它是程序的主要功能。

答案 2 :(得分:0)

更新:让我们详细说明答案...

我认为在文档中非常清楚:

  

退出Python。这是通过提高SystemExit来实现的   异常,因此try的finally子句指定的清理操作   声明被尊重,并且可以拦截出口   尝试外层

  

由于exit()最终“仅”引发异常,因此它只会退出   从主线程调用时的进程,而异常则不是   截获

中间缺少的段落与您的问题无关(主要是)。现在,这告诉我们sys.exit基本上通过引发SystemExit来实现,其中一个可选参数用于关闭虚拟机的代码(指定退出状态代码和消息)。 SystemExit JUST 是一个常规异常,这意味着很多事情:

  1. 可以抓住。也就是说,您可以编写except SystemExit块并阻止程序在某一点退出。
  2. 它将触发该点处堆栈中的所有finally块。您可以使用这些块进行适当的清理。这还包括您可能不知道的try: finally:块,因为上下文处理程序可能在__exit__方法上使用它们。
  3. 正如第二段提醒您的那样,只有程序中的主线程以特殊方式处理SystemExit。例外情况不会从一个线程传播到另一个线程,所以这只会在系统从主线程触发时退出。
  4. 总结一下,如果我们简化很多,Python的主线程看起来像这样:

     try:
         run_the_main_script()
     except SystemExit as e:
         invoke the registered "atexit" functions (in a LIFO way)
         check e, set exit status, and quit the program
    

    请注意,这不会为您执行任何特殊清理。虽然Python做了一些清理工作:调用已注册的清理函数,以受控方式销毁对象(这将刷新缓冲区等)。