繁体   English   中英

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

[英]Python: catch any exception and put it in a variable

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

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

def cleanupProcs(procs):
    if not procs:
        return

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

是否有迭代方法来做到这一点? 更优雅的方式? 一个更Pythonic的方式?

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

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

后来

raise the_type, the_value, the_traceback

(与此答案相关)

另请参见这里为Python 2.7。

在这种情况下,我想我会争辩说你可能做得不对。

对我来说,例外的一点是发出一个特殊情况的乞丐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")

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

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

就像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'

您可以使用:

procexceptions = []

except Exception, e:
    procexceptions.append(e)

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

raise procexceptions[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
>>> 

我可能会使用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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM