8

我经常发现自己想做这样的事情,我有一些东西包含在尝试中,除了这样

item= get_item()
try:
    do_work(item)
except SomeError as err:
    if err.code == 123:
        do_something(item)
    else:
        # Actually I don't want to do something with this error code... I want to handle in 'except'
except:
    put_back(item)
    raise

有没有办法except从其他地方提升到下面的街区?(acontinue会很好)我​​最终做了类似下面的事情,但不是那么干净

item= get_item()
try:
    try:
        do_work(item)
    except SomeError as err:
        if err.code == 123:
            do_something(item)
        else:
            raise
 except:
     put_back(item)
     raise

有没有办法做到这一点?

4

4 回答 4

9

如果您使用的是最新的 Python 版本(2.5 及更高版本),则应改用上下文管理器

class WorkItemContextManager(object):
    def __enter__(self):
        self.item = get_item()
        return self.item

    def __exit__(self, exc_type, exc_value, tb):
        if exc_type is not None:
            if exc_type is SomeError and exc_value.code == 123:
                do_something(self.item)
                return True  # Exception handled
            put_back(self.item)

然后:

with WorkItemContextManager() as item:
    do_work(item)

__exit__如果处理了异常,该方法可以返回 True;返回 None 将改为重新引发with块中引发的任何异常。

如果没有,您正在寻找一个finally块:

item = get_item()
try:
    do_work(item)
    item = None
except SomeError as err:
    if err.code == 123:
        do_something(item)
        item = None
finally:
    if item is not None:
        put_back(item)

finally套件保证在try:套件完成发生异常时执行。通过设置itemNone你基本上告诉finally套件一切都完成了就好了,不需要把它放回去。

处理程序从您的finally毯子处理程序接管except。如果 中出现异常do_workitem则不会设置为 None。如果SomeError处理程序没有捕获到异常,或者err.code不是123,也不会设置为 None,因此该方法被执行。itemput_back(item)

于 2012-09-11T17:16:02.903 回答
2

我的建议是创建一个函数(或一系列函数)来包装您想要控制的抛出错误的方法。就像是...

def wrapper(arg):
    try:      
        do_work(arg)
    except SomeError as e:
        if e.code == 123:
           do_something(item)
           # Other possible cleanup code
        else:
           raise

...然后,当您想调用它时...

try:
    wrapper(arg)
except SomeError as e:
    put_back(arg)
于 2012-09-11T17:31:31.040 回答
2

上下文管理器非常好,但是对于一些您不会在其他任何地方重用逻辑的简单情况,它们可能有点重。

except您可以在单个块内测试异常,而不是尝试拥有多个块except

item= get_item()
try:
    do_work(item)
except Exception as err:
    if isinstance(err, SomeError) and err.code == 123:
        do_something(item)
    else:
        put_back(item)
        raise

请注意,无论如何,这几乎就是上下文管理器的__exit__方法最终的样子。

请注意,真正属于其中的代码finally不会在这里结束。

于 2017-01-02T18:52:31.407 回答
1

最好记住 try-except 流的用途,它们的优点之一是它们不需要状态变量和状态检查,例如

if not foo:
    # do something

此外,Exception 类应该代表一种特定类型的错误。如果您需要对 except 块中的错误类型做出进一步决定,这是一个好兆头,表明该类不够具体,无法表示程序状态。你最好的选择是继承 SomeError 并且只在第一个 except 中捕获子类。然后 SomeError 的其他实例将落入第二个 except 块。

于 2012-09-11T17:24:42.457 回答