当我使用标准logging
包从greenlet中打印出日志语句时,我得到的文本如下:
2014-02-06 22:38:43,428 [INFO] (11396-Dummy-2) event_listener: About to block
我指的是11396-Dummy-2
部分。我希望它能说出像'Main'或'Listener 1'这样的东西。这可能吗?从当前的文档中我没有看到任何API这样做。
答案 0 :(得分:5)
我不确定日志中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
答案 1 :(得分:3)
注意,如果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)。