當我從使用標準logging
包greenlets內打印出日誌語句,我得到的文字,看起來像這樣:我可以在記錄時爲gevent greenlet設置顯示的自定義名稱嗎?
2014-02-06 22:38:43,428 [INFO] (11396-Dummy-2) event_listener: About to block
,我指的是11396-Dummy-2
部分。例如,我希望它能說'Main'或'Listener 1'。這可能嗎?從目前的文檔我沒有看到任何API來這樣做。
當我從使用標準logging
包greenlets內打印出日誌語句,我得到的文字,看起來像這樣:我可以在記錄時爲gevent greenlet設置顯示的自定義名稱嗎?
2014-02-06 22:38:43,428 [INFO] (11396-Dummy-2) event_listener: About to block
,我指的是11396-Dummy-2
部分。例如,我希望它能說'Main'或'Listener 1'。這可能嗎?從目前的文檔我沒有看到任何API來這樣做。
我不確定日誌中的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
請注意,如果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)。
這應該是被接受的答案。由於它使用日誌記錄適配器和標準gevent功能。 – Realistic