Is it possible to access the context object (code block) inside the __exit__() method of a context manager?
我想在exit()方法中再次调用代码对象,如果它引发异常(可能是几次,可能有延迟)。 我知道装饰器很容易,但我的动机是有时候我想重复一些代码片段,我不想提取到一个单独的函数并装饰它。 我正在寻找这些方面的东西:
1 2 3 4 5 6 7 8 | class again(object): def __enter__(self): pass def __exit__(self, exc_type, exc_val, exc_tb): if exc_type is not None: ???? # Invoke the code object again return True # eat exception |
它会像这样使用:
1 2 3 4 5 6 | x = 0 with again(): print x x += 1 if x == 1: raise Exception('I hate 1') |
而预期的产出将是:
1 2 | 0 1 |
我可以找到一种方法来获取代码对象。 没有任何上下文管理器属性似乎引用它(我想这不是真正需要的,因为它的工作只是在前后做事)。
有可能吗?
你可以通过一个例子看到这个:
1 2 3 4 5 6 7 8 9 10 11 12 | import contextlib import dis @contextlib.contextmanager def silly(): yield def foo(): print"Hello" with silly(): print"Inside" print"Goodbye" |
然后
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | >>> dis.dis(foo.__code__) 2 0 LOAD_CONST 1 (u'Hello') 3 PRINT_ITEM 4 PRINT_NEWLINE 3 5 LOAD_GLOBAL 0 (silly) 8 CALL_FUNCTION 0 11 SETUP_WITH 10 (to 24) 14 POP_TOP 4 15 LOAD_CONST 2 (u'Inside') 18 PRINT_ITEM 19 PRINT_NEWLINE 20 POP_BLOCK 21 LOAD_CONST 0 (None) >> 24 WITH_CLEANUP 25 END_FINALLY 5 26 LOAD_CONST 3 (u'Goodbye') 29 PRINT_ITEM 30 PRINT_NEWLINE 31 LOAD_CONST 0 (None) 34 RETURN_VALUE |
您可以看到