gpt4 book ai didi

Python 上下文管理器到装饰器(反之亦然)

转载 作者:行者123 更新时间:2023-12-01 03:50:57 24 4
gpt4 key购买 nike

我想要:

# Simple example, one could replace try/except by any other nested construct
def mycontextmanager_generator(foo):
try:
yield
except:
print 'bar'
  raise

mycontextmanager = build_contextmanager(mycontextmanager_generator)
mydecorator = build_decorator(mycontextmanager_generator)


>>> with mycontextmanager():
>>> raise Exception('baz gone bar in context manager')
... bar


>>> @mydecorator()
>>> def bazzer():
>>> raise Exception('baz gone bar in decorator')
>>> bazzer()
... bar

在此示例中,我从生成器函数构建了上下文管理器,并从同一函数构建了装饰器。这就是我试图以不成功的方式实现的目标。

更一般地说,我想要的是 DRY:编写一次 try/except block ,然后通过装饰器重复使用它上下文管理器 再次强调:无论是在生成器函数还是任何其他包装器中,仅编写一次 try/except block 。

ContextDecorator 东西(在 py3 中的 contextlib/py2 中的 contextlib2 中)只能与类一起使用,但在那种情况...我错过了什么吗?有没有办法使用 __enter__ 和 __exit__ 和基于类的 ContextManager 来实现我的 try/except block ?

或者是否有可能将使用 yield 语法构建的上下文管理器转换为装饰器?

或者相反(装饰器到上下文管理器)?

如果不是,我很高兴知道 Python 在这方面的限制是什么。

据我了解,yield 语法与 Python 解释器和上下文切换紧密相关,我不知道是否可以改变它在这一点上的行为。

最佳答案

比 Dunes 的解决方案更容易理解的解决方案,尽管没有利用 ContextDecorator 双语法。

import contextlib
import functools

def handler():
try:
yield
except:
print 'bar'


my_contextmanager = contextlib.contextmanager(handler)


def my_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
with my_contextmanager():
func(*args, **kwargs)
return wrapper


with my_contextmanager():
raise Exception('baz')

@my_decorator
def f():
raise Exception('baz')

f()

给出:

bar
bar

关于Python 上下文管理器到装饰器(反之亦然),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38264864/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com