当我使用标准logging
软件包从绿色内部打印出日志语句时,我会得到看起来像这样的文本:
2014-02-06 22:38:43,428 [INFO] (11396-Dummy-2) event_listener: About to block
我指的是11396-Dummy-2
部分。例如,我想说的是说"主"或"听众1"之类的话。这可能吗?从当前的文档我看不到任何API。
我不确定日志中的 11396-Dummy-2
部分来自何处,但是如果要在日志中添加上下文信息(例如greenlet标识符),则有一个数字有记录的方法。这是一个示例,使用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
模块是猴子绘制的,则将线程映射到绿色。特别是猴子补丁替代了_start_new_thread()
(因此,它启动了新的绿色),以及_get_ident()
(每当需要线程ID时,返回greenlet ID)。多亏了此映射,每当您询问当前线程时,实际上您会得到一个虚拟Thread
对象实例与当前运行的Greenlet关联!
因此,完全有可能执行以下操作:
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
代码检索当前线程名称时,它都会获取人均名称。我承认这有点黑客,但是在我当前的项目中效果很好。
这是概念证明:
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
模块进行修补(请参阅此答案)。