这通常是通过上下文管理器完成的。
import contextlib
@contextlib.contextmanager
def with_preparation():
prepare()
yield
done()
with preparation():
xyz.foo(<args>)
with preparation():
xyz.bar(<args>)
with preparation():
xyz.foobar()
preparation
定义一个函数,该函数返回
上下文管理器
这个
with
语句通过调用上下文管理器的
__enter__
方法,然后执行主体,然后确保上下文管理器
__exit__
方法在继续之前被调用(无论是由于引发异常还是由于正文正常完成)。
contextlib.contextmanager
提供了一种使用生成器函数定义上下文管理器的简单方法,而不是使用显式
__进入__
和
__退出__
方法。
您提到,对于特定模块中的每个函数,都需要这个。如果没有关于该模块的确切细节,这可能并不完全正确,但您可能可以在其基础上进一步扩展。
class XYZWrapper:
def __getattr__(self, name):
# Intentionally let an AttributeError propagate upwards
f = getattr(xyz, name)
def _(self, *args, **kwargs):
prepare()
return f(*args, **kwargs)
done()
setattr(XYZWrapper, name, _)
return _
prepared = XYZWrapper()
prepared.foo(<args>)
prepared.bar(<args>)
prepared.foobar()
简而言之,任何属性都可以访问
XYZWrapper
实例尝试在
xyz
模块,如果成功,则定义一个调用
prepare()
和
done()
根据需要进行修补
XYZWrapper
实例使用新包装器。