我正在开发类似日志记录组件的东西,我想像这样使用它:
with logging.Log(context='A', message='msg1') # with1
do_stuff()
如您所见,Log实现了一个with语句上下文管理器。此外,Log将context
存储为成员变量。假设我按如下方式实施do_stuff
:
def do_stuff():
with logging.Log(message='msg2') # with2
do_other_stuff()
这意味着在“with1”中调用“with2”。
问题是,有没有办法访问“with1”的成员?我玩inspect
但到目前为止没有运气。我知道我可以将Log分配给变量并传递它。我不想这样做,因为它会混淆很多代码。有什么想法吗?
我想重复使用context
。
答案 0 :(得分:2)
你试过这个吗?
with logging.Log(context='A', message='msg1') as outer:
do_stuff(outer)
def do_stuff(outer):
with logging.Log(message='msg2'):
print(outer.context, outer.message)
do_other_stuff()
答案 1 :(得分:1)
这是可能的,但只有全局或接近全局的状态,它可能会变得混乱:
# Thread-unsafe version
class Log(...):
logger_stack = []
def __enter__(self):
Log.logger_stack.append(self)
def __exit__(self, *args):
Log.logger_stack.pop()
这使得记录器可以从其他活动的with
语句中访问记录器,但是您无法安全地在不同的线程中同时使用它们。线程本地存储可以解决线程安全问题... ...:
# Thread-safeish version
class Log(...):
thread_local = threading.local()
def __enter__(self):
try:
Log.thread_local.logger_stack.append(self)
except AttributeError:
Log.thread_local.logger_stack = [self]
def __exit__(self, *args):
Log.thread_local.logger_stack.pop()
现在,不同的线程不会看到或干扰彼此的日志记录上下文。这可以防止一些错误,但这也意味着如果你做了类似
的事情with logging.Log(...):
delegate_to_another_thread()
在另一个线程中发生的工作不会看到第一个线程的日志记录上下文。