如何从Python退出而无需追溯?


277

我想知道如何在不对输出进行回溯转储的情况下退出Python。

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

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


8
sys.exit()会在不打印回溯的情况下停止执行,并引发Exception ...您的问题恰好描述了默认行为,因此请不要进行任何更改。
Luper Rouch

@Luper检查sys.exit()是否抛出SystemExit很容易!
2012年

4
我说过它不会打印回溯,不是说它不会引发异常。
卢珀·鲁什(Luper Rouch)2012年

我认为这确实解决了你问的问题:stackoverflow.com/questions/173278/...
斯特凡

2
这个问题是专门针对Jython 2.4还是类似的东西?因为对于现代版本的Python(即使在2009年,这意味着CPython 2.6和3.1,Jython 2.5和IronPython 2.6),这个问题没有任何意义,而且最重要的答案是错误的。
abarnert 2014年

Answers:


300

您大概遇到了一个异常,因此程序正在退出(带有追溯)。因此,要做的第一件事是在干净退出之前捕获该异常(可能带有消息,给出示例)。

在您的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()

2
开始时应该有类似“ from sys import exit”的内容。
罗布

10
如果在“主程序”中调用sys.exit(),则上面的代码将丢弃传递给sys.exit的值。请注意,sys.exit引发SystemExit,并且变量“ e”将包含退出代码。
bstpierre

5
我建议在stderr sys.stderr.write(msg)中打印
vinilios 2012年

14
强烈建议从取出线except Exception:sys.exit(0),包容性。在所有未处理的异常上打印回溯并在代码结束后退出,这已经是默认行为,那么为什么要手动进行相同的操作呢?
MestreLion

6
@jkp-关于您的评论:sys.exit()应用于程序。exit()适用于交互式外壳。请参见Python中exit()和sys.exit()之间的区别?
ire_and_curses

81

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

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和call下运行的代码来执行此操作fork()。当分叉过程出现时,单元测试就会进行SystemExit。这绝对是一个极端的情况!


4
-1:此代码很愚蠢:为什么要抓住SystemExit只是打电话sys.exit(e)?删除两条线具有相同的效果。另外,清理属于finally:,不属于except Exception: ... raise
MestreLion,2012年

@MestreLion:您可以随意投票,但是如果您在我的评论之上读了我的评论,那仅适用于2.5+。如果您阅读了我所有的文章,我明确表示该代码很愚蠢,并准确建议了您在评论中所说的内容。
bstpierre 2012年

2
抱歉,您是对的...我忘记了Python 2.5中对异常的重大重新组织。我试图撤消下降投票,但是只有在答案被编辑后,SO才允许我撤消。因此,既然我们处于2012年,并且Python 2.4是古老的历史,为什么不编辑它并预先显示正确的(当前)代码,而将2.5之前的方法留作脚注呢?它将大大改善答案,我将能够撤消下降投票,并将很乐意这样做。双赢:)
MestreLion

@MestreLion:我按照您的建议开始进行编辑,但是此答案仅在问题和2.4环境下才有意义。不赞成投票不会让我不高兴。
bstpierre 2012年


9

import sys; sys.exit(0)什么?


@mestreLion然后为什么要获取Dets 06 18:53:17回溯(最近一次调用最近):<module> import sys中的文件“ debug_new.py”,第4行;sys.exit(0)SystemExit:控制台中的org.python.core.PyException.fillInStackTrace(PyException.java:70)为0?
2012年

3
@Val:因为您没有使用标准的python控制台。Jython不是Python,它看起来(或至少是它的控制台)以不同的方式处理异常。
MestreLion



4

最好避免使用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

如果发生任何其他错误,我们仍将获得完整的追溯输出。


1
有关sys.trackbacklimit在Python 3中使用的信息,请参见此答案
Acumenus


2

我会这样:

import sys

def do_my_stuff():
    pass

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

0

关于什么

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

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


-8
# 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

7
如果您要注释代码,则可以提高答案的质量。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.