我想在不退出的情况下捕获和记录异常,例如,

try:
    do_stuff()
except Exception as err:
    print(Exception, err)
    # I want to print the entire traceback here,
    # not just the exception name and details

我想打印与抛出异常时打印的完全相同的输出,而不使用try/,只是拦截异常,并且我不希望它退出程序。


当前回答

你可以这样做:

try:
    do_stuff()
except Exception, err:
    print(Exception, err)
    raise err

其他回答

您需要将try/except放在可能发生错误的最内层循环中,即。

for i in something:
    for j in somethingelse:
        for k in whatever:
            try:
                something_complex(i, j, k)
            except Exception, e:
                print e
        try:
            something_less_complex(i, j)
        except Exception, e:
            print e

... 等等

换句话说,您需要将可能在try/中失败的语句包装在尽可能具体的内部循环中。

您需要traceback模块。它将允许您像Python通常那样打印堆栈转储。特别是,print_last函数将打印最后一个异常和堆栈跟踪。

import io
import traceback

try:
    call_code_that_fails()
except:

    errors = io.StringIO()
    traceback.print_exc(file=errors)  # Instead of printing directly to stdout, the result can be further processed
    contents = str(errors.getvalue())
    print(contents)
    errors.close()

其他一些答案已经指出了回溯模块。

请注意,使用print_exc,在某些极端情况下,您将无法获得您所期望的结果。在Python 2.x中:

import traceback

try:
    raise TypeError("Oups!")
except Exception, err:
    try:
        raise TypeError("Again !?!")
    except:
        pass

    traceback.print_exc()

...将显示上一个异常的回溯:

Traceback (most recent call last):
  File "e.py", line 7, in <module>
    raise TypeError("Again !?!")
TypeError: Again !?!

如果你真的需要访问原始的回溯,一个解决方案是将exc_info返回的异常信息缓存到一个局部变量中,并使用print_exception显示它:

import traceback
import sys

try:
    raise TypeError("Oups!")
except Exception, err:
    try:
        exc_info = sys.exc_info()

        # do you usefull stuff here
        # (potentially raising an exception)
        try:
            raise TypeError("Again !?!")
        except:
            pass
        # end of useful stuff


    finally:
        # Display the *original* exception
        traceback.print_exception(*exc_info)
        del exc_info

生产:

Traceback (most recent call last):
  File "t.py", line 6, in <module>
    raise TypeError("Oups!")
TypeError: Oups!

但这也有一些陷阱:

From the doc of sys_info: Assigning the traceback return value to a local variable in a function that is handling an exception will cause a circular reference. This will prevent anything referenced by a local variable in the same function or by the traceback from being garbage collected. [...] If you do need the traceback, make sure to delete it after use (best done with a try ... finally statement) but, from the same doc: Beginning with Python 2.2, such cycles are automatically reclaimed when garbage collection is enabled and they become unreachable, but it remains more efficient to avoid creating cycles.


另一方面,通过允许你访问与异常相关的回溯,Python 3产生了一个不那么令人惊讶的结果:

import traceback

try:
    raise TypeError("Oups!")
except Exception as err:
    try:
        raise TypeError("Again !?!")
    except:
        pass

    traceback.print_tb(err.__traceback__)

... 将显示:

  File "e3.py", line 4, in <module>
    raise TypeError("Oups!")

你可以这样做:

try:
    do_stuff()
except Exception, err:
    print(Exception, err)
    raise err