关于python:关于sys.exit和SystemExit的困惑

Confusion about sys.exit and SystemExit

我已经阅读了一些关于so的线程和关于SystemExit异常的python文档。这个线程不打算是重复的,因为我在类似的线程中没有找到答案。

调用sys.exit()和提升systemeexit是否都进行清理?我知道sys.exit调用systemeexit,但如果您只提出systemeexit异常,它会为您做任何清理吗?官方的python文档对此不太清楚。我问这个问题的原因是因为我的一个同事认为SystemExit在代码中写得更清楚,而您不需要导入sys模块……但只是引发一个异常,我不确定与调用sys.exit相比是否正在进行任何清理,后者在调用SystemExit之前会从我所知道的内容中进行清理。


打电话给sys.exit()只会提高SystemExit。在返回堆栈的过程中,执行清理的是异常处理,因此这两种技术将执行相同的清理。但无论如何,你应该使用sys.exit而不是SystemExit:试图节省一个sys的进口没有意义,这不需要任何成本。调用sys.exit是结束Python进程的常规方法。

也就是说,您确定要在代码中显式地退出进程吗?这使得你的功能很难再利用。通常,当简单地从函数返回时,人们使用sys.exit也可以,因为它是程序的主要功能。


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


更新:让我们详细说明一下答案…

我觉得医生很清楚:

Exit from Python. This is implemented by raising the SystemExit
exception, so cleanup actions specified by finally clauses of try
statements are honored, and it is possible to intercept the exit
attempt at an outer level

Since exit() ultimately"only" raises an exception, it will only exit
the process when called from the main thread, and the exception is not
intercepted

中间缺失的段落与你的问题(大部分)无关。现在,这告诉我们,sys.exit基本上是通过提升SystemExit来实现的,带有一个可选参数,用于关闭虚拟机的代码(指定退出状态代码和消息)。SystemExit只是一个常规的例外,它意味着许多事情:

  • 它可以被抓住。也就是说,您可以编写一个except SystemExit块,防止程序在某一点退出。
  • 它将触发该点堆栈中的所有finally块。您可以使用这些块进行适当的清理。这还包括您可能不知道的try: finally:块,因为上下文处理程序可能在其__exit__方法上有它们。
  • 正如第二段提醒您的,只有程序中的主线程以特殊的方式处理SystemExit。并且异常不会从一个线程传播到另一个线程,因此只有在系统从主线程触发时,才会使系统退出。
  • 总结一下,如果我们简化很多,python的主线程如下所示:

    1
    2
    3
    4
    5
     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执行某些清理:调用已注册的清理函数,以受控方式销毁对象(这将刷新缓冲区等)。