如何在没有回溯的情况下退出 Python?

Posted

技术标签:

【中文标题】如何在没有回溯的情况下退出 Python?【英文标题】:How to exit from Python without traceback? 【发布时间】:2010-11-14 08:24:15 【问题描述】:

我想知道如何在没有输出回溯转储的情况下退出 Python。

我仍然希望能够返回错误代码,但我不想显示回溯日志。

我希望能够使用exit(number) 退出而无需跟踪,但如果出现异常(不是退出),我需要跟踪。

【问题讨论】:

sys.exit() 停止执行而不打印回溯,引发异常确实......您的问题准确描述了默认行为是什么,所以不要更改任何内容。 @Luper 很容易检查 sys.exit() 是否抛出 SystemExit! 我说它不会打印回溯,并不是说它不会引发异常。 我认为这确实回答了您提出的问题:***.com/questions/173278/… 这个问题是专门针对 Jython 2.4 还是类似的?因为对于现代版本的 Python(即使在 2009 年,这意味着 CPython 2.6 和 3.1、Jython 2.5 和 IronPython 2.6),这个问题毫无意义,而且最重要的答案都是错误的。 【参考方案1】:

您可能遇到了异常,因此程序正在退出(带有回溯)。因此,首先要做的是在干净退出之前捕获该异常(可能带有消息,给出示例)。

在您的 main 例程中尝试这样的操作:

import sys, traceback

def main():
    try:
        do main program stuff here
        ....
    except KeyboardInterrupt:
        print "Shutdown requested...exiting"
    except Exception:
        traceback.print_exc(file=sys.stdout)
    sys.exit(0)

if __name__ == "__main__":
    main()

【讨论】:

开头应该有“from sys import exit”之类的东西。 如果在“主程序的东西”中调用 sys.exit(),上面的代码会丢弃传递给 sys.exit 的值。请注意 sys.exit 引发 SystemExit 并且变量“e”将包含退出代码。 我建议在 stderr sys.stderr.write(msg) 中打印 强烈建议删除从 except Exception:sys.exit(0) 的行,包括在内。在所有未处理的异常上打印回溯并在代码结束后退出已经是默认行为,那么为什么还要手动执行相同的操作呢? @jkp - 关于您的评论:sys.exit() 应该用于程序。 exit() 用于交互式 shell。见The difference between exit() and sys.exit() in Python?。【参考方案2】:

也许您正在尝试捕获所有异常,而这是捕获由sys.exit() 引发的SystemExit 异常?

import sys

try:
    sys.exit(1) # Or something that calls sys.exit()
except SystemExit as e:
    sys.exit(e)
except:
    # Cleanup and reraise. This will print a backtrace.
    # (Insert your cleanup code here.)
    raise

一般来说,使用except: 而不命名异常是一个坏主意。你会捕捉到各种你不想捕捉的东西——比如SystemExit——它还可以掩盖你自己的编程错误。我上面的例子很愚蠢,除非你在清理方面做一些事情。您可以将其替换为:

import sys
sys.exit(1) # Or something that calls sys.exit().

如果你需要在不引发SystemExit的情况下退出:

import os
os._exit(1)

我这样做,在 unittest 下运行并调用 fork() 的代码中。当分叉进程引发SystemExit 时,单元测试会得到。这绝对是一个极端案例!

【讨论】:

-1:这段代码很傻:为什么抓住SystemExit只是为了调用sys.exit(e)?删除这两行具有 same 效果。此外,清理属于finally:,而不是except Exception: ... raise @MestreLion:您可以随意投反对票,但如果您阅读我的评论就在您的评论上方,那仅适用于 2.5+。如果您阅读了我的所有帖子,我明确表示代码很愚蠢,并准确地建议了您在评论中所说的内容。 对不起,你是对的......我忘记了 Python 2.5 中对异常进行了重大的重组。我试图撤消否决票,但只有在编辑答案时才允许我这样做。所以,既然我们是在 2012 年,而 Python 2.4 是古老的历史,为什么不编辑它并预先显示正确的(当前)代码,将 2.5 之前的方法作为脚注呢?它将大大改善答案,我将能够撤消反对票,并且很乐意这样做。人人共赢 :) @MestreLion:我按照你的建议开始编辑,但这个答案真的只在问题的上下文和 2.4 环境中才有意义。否决票并没有让我感到不安。【参考方案3】:
import sys
sys.exit(1)

【讨论】:

【参考方案4】:

以下代码不会引发异常,并且会在没有回溯的情况下退出:

import os
os._exit(1)

See this question and related answers 了解更多详情。很惊讶为什么所有其他答案都如此复杂。

【讨论】:

【参考方案5】:

类似import sys; sys.exit(0) 的东西?

【讨论】:

@mestreLion 那我为什么会得到 Dets 06 18:53:17 Traceback(最近一次调用最后):文件“debug_new.py”,第 4 行,在 import sys; sys.exit(0) SystemExit: 0 at org.python.core.PyException.fillInStackTrace(PyException.java:70) 在我的控制台中? @Val:因为您没有使用标准的 python 控制台。 Jython 不是 Python,看起来它(或至少它的控制台)处理异常的方式不同。 @Val 见Why is sys.exit() causing a traceback?【参考方案6】:

最好避免使用 sys.exit() 而是引发/处理异常以使程序干净地完成。如果要关闭回溯,只需使用:

sys.trackbacklimit=0

您可以在脚本顶部设置它以压缩所有回溯输出,但我更喜欢谨慎使用它,例如“已知错误”我希望输出干净,例如在 foo.py 文件中:

import sys
from subprocess import *

try:
  check_call([ 'uptime', '--help' ])
except CalledProcessError:
  sys.tracebacklimit=0
  print "Process failed"
  raise

print "This message should never follow an error."

如果 CalledProcessError 被捕获,输出将如下所示:

[me@test01 dev]$ ./foo.py
usage: uptime [-V]
    -V    display version
Process failed
subprocess.CalledProcessError: Command '['uptime', '--help']' returned non-zero exit status 1

如果发生任何其他错误,我们仍然会得到完整的回溯输出。

【讨论】:

有关在 Python 3 中使用 sys.trackbacklimit,请参阅 this answer。【参考方案7】:

使用内置的python函数quit()就可以了。 无需导入任何库。 我正在使用 python 3.4

【讨论】:

【参考方案8】:

我会这样做:

import sys

def do_my_stuff():
    pass

if __name__ == "__main__":
    try:
        do_my_stuff()
    except SystemExit, e:
        print(e)

【讨论】:

【参考方案9】:

怎么样

import sys
....
....
....
sys.exit("I am getting the heck out of here!")

没有回溯,并且以某种方式更明确。

【讨论】:

【参考方案10】:
# Pygame Example  

import pygame, sys  
from pygame.locals import *

pygame.init()  
DISPLAYSURF = pygame.display.set_mode((400, 300))  
pygame.display.set_caption('IBM Emulator')

BLACK = (0, 0, 0)  
GREEN = (0, 255, 0)

fontObj = pygame.font.Font('freesansbold.ttf', 32)  
textSurfaceObj = fontObj.render('IBM PC Emulator', True, GREEN,BLACK)  
textRectObj = textSurfaceObj.get_rect()  
textRectObj = (10, 10)

try:  
    while True: # main loop  
        DISPLAYSURF.fill(BLACK)  
        DISPLAYSURF.blit(textSurfaceObj, textRectObj)  
        for event in pygame.event.get():  
            if event.type == QUIT:  
                pygame.quit()  
                sys.exit()  
        pygame.display.update()  
except SystemExit:  
    pass

【讨论】:

如果您对代码进行注释,将会提高答案的质量。

以上是关于如何在没有回溯的情况下退出 Python?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不使用“除外”python的情况下退出不和谐机器人

在这个“生成括号”问题中,回溯是如何工作的?

如何在不退出 python 脚本的情况下销毁一个 QApplication 然后运行一个新的?

算法回溯:如何在不存储状态的情况下进行递归

如何在不保存的情况下退出 Eclipse

如何在不使用终端的情况下退出 omxplayer?