2014-02-07 20 views

回答

3

我不確定日誌中的11396-Dummy-2部分來自哪裏,但是如果您想向日志添加上下文信息(例如greenlet標識符),則有a number of documented ways這樣做。下面是一個例子,使用LoggerAdapter

import logging 
import gevent 

class Adapter(logging.LoggerAdapter): 
    def process(self, msg, kwargs): 
     msg = '(%s) %s' % (gevent.getcurrent()._run.__name__, msg) 
     return msg, kwargs 

logger = Adapter(logging.getLogger(), {}) 

def foo(): 
    logger.debug('Running in foo') 
    gevent.sleep(0) 
    logger.debug('Explicit context switch to foo again') 

def bar(): 
    logger.debug('Explicit context to bar') 
    gevent.sleep(0) 
    logger.debug('Implicit context switch back to bar') 

logging.basicConfig(level=logging.DEBUG, 
        format='%(levelname)s %(threadName)s %(message)s') 
gevent.joinall([ 
    gevent.spawn(foo), 
    gevent.spawn(bar), 
]) 

運行時,這應該打印

DEBUG MainThread (foo) Running in foo 
DEBUG MainThread (bar) Explicit context to bar 
DEBUG MainThread (foo) Explicit context switch to foo again 
DEBUG MainThread (bar) Implicit context switch back to bar 
+0

這應該是被接受的答案。由於它使用日誌記錄適配器和標準gevent功能。 – Realistic

2

請注意,如果threading模塊猴子打補丁,線程幾乎映射到greenlets。特別是猴子補丁替換_start_new_thread()(所以它啓動一個新的greenlet),以及_get_ident()(所以每當需要線程ID時返回greenlet ID)。感謝這個映射,無論何時詢問當前線程,實際上你都會得到一個與當前正在運行的greenlet相關聯的虛擬Thread對象實例!

因此,這是完全可以做到以下幾點:

import gevent.monkey 
gevent.monkey.patch_thread() 

from threading import current_thread 

# and then, at the start of the greenlet 
current_thread().name = "MyNewName" 

現在,每當logging代碼檢索當前線程的名稱,它得到每個greenlet名。我不得不承認這有點破綻,但在我目前的項目中效果很好。

而這裏的概念證明:

import gevent.monkey 
gevent.monkey.patch_thread() 

import logging 
from threading import current_thread 

logger = logging.getLogger() 

def foo(): 
    current_thread().name = "MyFoo" 
    logger.debug('Running in foo') 
    gevent.sleep(0) 
    logger.debug('Explicit context switch to foo again') 

def bar(): 
    current_thread().name = "MyBar" 
    logger.debug('Explicit context to bar') 
    gevent.sleep(0) 
    logger.debug('Implicit context switch back to bar') 

logging.basicConfig(level=logging.DEBUG, 
        format='%(levelname)s %(threadName)s %(message)s') 
gevent.joinall([ 
    gevent.spawn(foo), 
    gevent.spawn(bar), 
]) 

執行時,它打印:

DEBUG MyFoo Running in foo 
DEBUG MyBar Explicit context to bar 
DEBUG MyFoo Explicit context switch to foo again 
DEBUG MyBar Implicit context switch back to bar 

只要確保threading模塊任何其他進口前修補(見this answer)。

相關問題