2015-01-15 23 views
1

我嘗試使用twisted.python.context,但上下文在第一個deferToThread後消失。在扭曲中使用上下文

from twisted.internet import reactor, defer, threads 
from twisted.python import context 

def _print_context(msg): 
    cont = context.get('cont') 
    print "{msg}: {context}".format(msg=msg, context=cont) 

def sub_call(): 
    _print_context("In sub_call") 

@defer.inlineCallbacks 
def with_context(): 
    _print_context("before thread") 
    yield threads.deferToThread(sub_call) 
    _print_context("after thread") 
    reactor.stop() 

def test(): 
    cont = {'cont': "TestContext"} 
    context.call(cont, with_context) 
reactor.callLater(0, test) 
reactor.run() 

我有背景deferToThread之前和sub_call,但deferToThread後沒有上下文。

deferToThread之後有什麼方法可以有上下文嗎?

回答

3

context.call設置傳遞給它的對象調用期間的上下文 - 在本例中爲with_context

with_context是一個inlineCallbacks包裝的發電機功能。第一次調用它會創建一個新的生成器並將其重複至第一個yield聲明。然後它的執行被暫停,並且就呼叫者而言,呼叫返回。此時將彈出上下文堆棧並放棄提供的上下文。

稍後,執行inlineCallbacks可確保生成器將進一步迭代,以便執行yield語句之後的代碼。但是,上下文已被丟棄。

有沒有簡單的方法來解決這個問題。 twisted.python.context並未嘗試解決異步上下文管理的問題。此外,twisted.python.context是相當可怕的,如果任何程序實際上應該寫入使用它很少。

我建議退後一步,在這裏重新評估您的選擇。通過創建類並在其實例上使用實例屬性來在方法調用之間傳遞狀態,您可能會更好地服務於此類。

+1

非常感謝。當然,我使用類,這只是一個問題的最小例子。但只有我看到的解決方案是通過方法params傳遞上下文。我不喜歡這個解決方案,但找不到任何其他解決方案。 – aborilov

+0

我很好奇爲什麼你不喜歡將輸入傳遞給你的方法作爲參數的解決方案。 – Glyph

+0

@Glyph,因爲它是一個可選參數,每個方法中都會有這個參數,所以這些方法大部分都不需要這個參數,他們甚至不需要知道它存在,只需要將它傳遞給下一個方法。在此參數中,我傳遞有關在系統上執行操作的用戶的信息。而'context',我認爲是解決這個問題的最佳解決方案。 – aborilov