2014-09-04 67 views
0

我的工作就像一個日誌組件,我想用這樣的:訪問封閉「與」語句隱

with logging.Log(context='A', message='msg1') # with1 
    do_stuff() 

正如你可以看到日誌實現with語句的上下文管理。此外,Log將context存儲爲成員變量。比方說,我實現do_stuff如下:

def do_stuff(): 
    with logging.Log(message='msg2') # with2 
     do_other_stuff() 

這意味着「with2」是「配1」中調用。

問題是,有沒有辦法訪問「with1」的成員?我玩弄了inspect,但到目前爲止還沒有運氣。我知道我可以將Log分配給一個變量並傳遞給它。我不想這樣做,因爲它會混亂很多代碼。任何想法?

我想重複使用context

回答

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() 
+0

是的,我知道這會奏效。這就是我所說的「我可以將Log分配給一個變量並將其傳遞」。這會混亂很多的代碼,因爲有很多嵌套的函數... – 2014-09-04 22:49:40

+0

你可以在locals()和globals()中搜索,但我認爲試圖訪問未命名的變量會變得更加混亂,然後只傳遞參數(只是我的0.02美元)。 – user590028 2014-09-04 22:54:32

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

這種情況發生在其他線程的工作將不會看到第一個線程的上下文記錄。