Python:捕获任何异常并将其放入变量中

时间:2013-10-16 14:19:48

标签: python exception recursion

要弄清楚要避免一些递归需要什么,我需要捕获任何异常(编辑:不仅仅是从Exception派生的,而是所有异常,包括KeyboardInterrupt和用户异常),将它放在变量中,以后再在捕获区外重新抬起它。从本质上讲,我正试图推出自己的最终块。这可能吗?

实际问题是调用许多清理函数,如果其中任何一个失败,也应该调用其他所有函数,那么失败的函数的异常仍然应该传播。这是我目前的解决方案,它需要一个Popen对象列表:

def cleanupProcs(procs):
    if not procs:
        return

    proc = procs.pop(0)
    try:
        proc.terminate()
        proc.wait()
    finally:
        cleanupProcs(procs)

有迭代方法吗?更优雅的方式?更多的Pythonic方式?

7 个答案:

答案 0 :(得分:7)

如果你想要包括堆栈跟踪:

try:
    # something
except:
    the_type, the_value, the_traceback = sys.exc_info()

raise the_type, the_value, the_traceback

(与this answer相关)

另请参阅here了解Python 2.7。

答案 1 :(得分:2)

在这种情况下,我认为我认为你可能没有做得对。

对我而言,例外的一点是发出 bum bum baaaaa 特殊情况的信号。当您编写可能触发异常的代码时,您有两个负责任的选项 - 捕获它并用它做某事(如恢复),或者完全忽略它。

根据您在帖子中所说的内容,您并不关心发生异常。它不应该停止你的程序,程序流程应该继续正常。你然而想知道发生了异常。这就是记录模块的用武之地:

import logging
log = logging

def get_some_cheese():
    raise ValueError("Sorry, we're right out.")

try:
    get_some_cheese()
except:
    log.exception("What a waste of life")

当您记录异常时,它会自动为您添加stack trace信息。在稍微配置日志记录之后,您可以设置它来执行各种任何您想要做的事情 - 发送电子邮件,写入文件或stdout / err,等等。但是你会得到一个例外的消息,但你也可以简单地从错误中恢复并继续以快乐的方式清理你需要清理的任何东西。

答案 2 :(得分:0)

Openstack因其他原因做了非常相似的事情。看看https://github.com/openstack/nova/blob/master/nova/openstack/common/excutils.py#L30(函数save_and_reraise_exception)。在他们的情况下,它就像一个资源管理器。

答案 3 :(得分:0)

与Python中的其他所有内容一样,异常是对象,因此可以绑定到名称并进行操作。这是一个简短的示例,展示如何获取异常并在以后使用它:

>>> def to_int(x):
...     try:
...         return int(x)
...     except Exception, e:
...         print 'in exception block:', e
...     print 'after exception block:', e

>>> to_int('12')
12
>>> to_int('abc')
in exception block: invalid literal for int() with base 10: 'abc'
after exception block: invalid literal for int() with base 10: 'abc'

答案 4 :(得分:0)

你可以使用:

procexceptions = []

except Exception, e:
    procexceptions.append(e)

然后(在终止进程的循环之后)你可以

raise procexceptions[0]

等。

答案 5 :(得分:0)

很容易:

>>> try:
...     #something
... except BaseException, e: # OK. Using BaseException instead of Exception
...     pass
... 
>>> 
>>> raise e
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
>>> 

答案 6 :(得分:0)

我可能会使用BaseException来捕获任何被抛出的东西,并遍历所有清理函数(而不是使用递归)。然后在列表中附加任何异常,以便在完成清理时适当地处理(重新加注,记录等)。

def runCleanup(procs):
    exceptions = []
    for proc in procs:
        try:
            proc.terminate()
            proc.wait()
        except BaseException as e:
            exceptions.append(e) # Use sys.exc_info() for more detail

    return exceptions # To be handled or re-raised as needed