【问题标题】:Confusion about sys.exit and SystemExit关于 sys.exit 和 SystemExit 的困惑
【发布时间】:2014-10-26 19:30:32
【问题描述】:

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

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

【问题讨论】:

  • 不要忘记投票任何对您有帮助的答案。标记一个作为答案是特别好的。 ;)

标签: python


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    调用sys.exit() 只会引发SystemExit。它是在备份堆栈的过程中进行的异常处理进行清理,因此两种技术都将执行相同的清理。但是无论如何,您都应该使用sys.exit 而不是SystemExit:尝试保存一个sys 导入是没有意义的,这不会花费任何成本。调用sys.exit是结束Python进程的常规方式。

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

    【讨论】:

    • 这并不完全正确,因为 sys.exit() 函数根据我所知道的自行清理(根据 SystemExit 的文档,它说 sys.exit 在执行清理后调用 SystemExit但没有具体说明何时引发 SystemExit 本身)但在引发 SystemExit 时必须指定清理代码才有意义。
    • 你错了。 sys.exit() 函数实际上除了引发 SystemExit 之外什么都不做。 SystemExit 的文档没有说它执行清理。我不确定你读到了什么。
    【解决方案3】:

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

    我认为在文档中很清楚:

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

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

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

    1. 它可以被抓住。即,您可以编写一个except SystemExit 块并阻止程序在某个点退出。
    2. 它将触发此时堆栈中的所有finally 块。您可以使用这些块进行适当的清理。这还包括您可能不知道的 try: finally: 块,因为上下文处理程序可能在其 __exit__ 方法中包含它们。
    3. 正如第二段提醒你的那样,只有程序中的主线程以特殊的方式对待SystemExit。并且异常不会从一个线程传播到另一个线程,因此只有在主线程触发时才会使系统退出。

    总结一下,如果我们简化很多,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 会进行某些清理:调用已注册的清理函数,以受控方式销毁对象(这将刷新缓冲区等)。

    【讨论】:

    • 那你没有读够或者是误会了。 exit 不是 sys.exit,exit 是并且应该只在加载站点模块时在交互式 shell 中使用。
    • 正如我所说,from the documentation of sys.exit。文档很清楚。如果你不能阅读,那不是我的问题。顺便说一句:您负责清理,通过捕获异常或finally 块(也在文档中)
    • 没必要这么粗鲁吧?我知道它的stackoverflow,但来吧。是的,我可以阅读,不清楚 sys.exit() 函数是否进行了任何清理,但至少我现在知道
    • 好吧,我想告诉其他人他们看不懂或误解问题不是粗鲁吗?不管怎样,我读得很清楚,但我会在答案中为您详细说明...
    • 显然很粗鲁,因为我猜你知道一个 30 岁的人可以阅读?说他或她不能是对他们智力的直接侮辱。如果您要尝试帮助人们回答问题,您应该了解并非每个人都以相同的方式解释相同的文本,也不是每个人都理解每一件事,这就是拥有这样的论坛的原因
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-30
    • 2011-12-13
    • 2017-12-04
    • 2012-03-06
    • 1970-01-01
    • 1970-01-01
    • 2019-05-17
    相关资源
    最近更新 更多