访问"与"声明含蓄地说

时间:2014-09-04 22:43:46

标签: python stack-trace with-statement inspect

我正在开发类似日志记录组件的东西,我想像这样使用它:

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

2 个答案:

答案 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()

在另一个线程中发生的工作不会看到第一个线程的日志记录上下文。