Python gevent:调试旋转线程?

Python gevent:调试旋转线程?,python,gevent,Python,Gevent,在我基于gevent的程序中,我在某个地方有一个线程,它在一个循环中,类似于: while True: gevent.sleep(0) 我怎么知道这是哪根线?是否可以列出(并获取)正在运行的线程的堆栈跟踪?方法1。超时 我在代码中使用它来跟踪可能阻塞的greenlet。发生这种情况时,将引发NodeTaskTimeout。只需将作业包装为超时,或为它们提供超时对象 with Timeout(90, False): task_jobs.join() i

在我基于gevent的程序中,我在某个地方有一个线程,它在一个循环中,类似于:

while True:
    gevent.sleep(0)
我怎么知道这是哪根线?是否可以列出(并获取)正在运行的线程的堆栈跟踪?

方法1。超时 我在代码中使用它来跟踪可能阻塞的greenlet。发生这种情况时,将引发NodeTaskTimeout。只需将作业包装为超时,或为它们提供超时对象

 with Timeout(90, False):
        task_jobs.join()
    
    if task_jobs:
        print 'task jobs killed', task_jobs
        task_jobs.kill()
        if settings.DEBUG:
            raise NodeTaskTimeout
如果此打印挂起/阻塞/花费的时间太长,则它将退出任务。 尤其令人讨厌的是那些相互依赖并导致僵局的工作 job1/thread->job2/thread2->job3/thread3和job3/thread3仅在job1完成时完成,这是永远不会发生的,因为job2未完成,而job2未完成是因为job3未完成。。你明白了;)

方法2设置跟踪


但是,您还需要将怀疑正在“旋转”的代码放入with块中。

有一个用于检查该块的官方API,它将精确定位导致该块的确切行,检查下面的代码示例:

# gevent        1.3.7
# greenlet      0.4.15
# zope.event    4.4
import gevent
from gevent import config, get_hub
from gevent.events import IEventLoopBlocked
import logging
from pprint import pformat
import time
import zope.event

# initial logging
logging.basicConfig(level=logging.INFO)
log = logging.getLogger(__name__)

# setup gevent config
# enable the monitor thread
config.monitor_thread = True
config.max_blocking_time = 4

# start the monitor thread
hub = get_hub()
monitor = hub.start_periodic_monitoring_thread()

# register the event to logging system
def g(event):
    log.error('Greenlet: {}, exceed the max blocking time: {}'.format(event.greenlet, event.blocking_time))
    log.error(pformat(event.info))
event = IEventLoopBlocked()
zope.event.subscribers.append(g)

# you can also create you own monitoring function
# def check(hub):
#     print('< periodic check in monitoring thread >')
#
# monitor.add_monitoring_function(check, 1)

def gl1():
    # use time.sleep to trigger block
    log.info('block at gl1 for 2 seconds')
    time.sleep(2)
    log.info('leave gl1 now')

def gl2():
    # use time.sleep to trigger block
    log.info('block at gl2 for 6 seconds should be detected')
    time.sleep(6)
    log.info('leave gl2 now')

def gl3():
    # gevent.sleep will not block
    log.info('gl3 will not block since it use gevent.sleep')
    gevent.sleep(8)
    log.info('leave gl3 now')


gevent.joinall([
    gevent.spawn(gl3),
    gevent.spawn(gl1),
    gevent.spawn(gl2),
])
#gevent 1.3.7
#绿色0.4.15
#zope.event 4.4
导入gevent
从gevent导入配置中,获取
从gevent.events导入IEventLoopBlocked
导入日志记录
从pprint导入pformat
导入时间
导入zope.event
#初始记录
logging.basicConfig(级别=logging.INFO)
log=logging.getLogger(_名称__)
#设置gevent配置
#启用监视器线程
config.monitor\u thread=True
config.max\u阻塞时间=4
#启动监视器线程
hub=get_hub()
monitor=hub.start\u periodic\u monitoring\u thread()
#将事件注册到日志记录系统
def g(事件):
log.error('Greenlet:{},超过最大阻塞时间:{}'。格式(event.Greenlet,event.blocking_time))
日志错误(pformat(event.info))
事件=IEventLoopBlocked()
zope.event.subscribers.append(g)
#您还可以创建自己的监控功能
#def检查(轮毂):
#打印(“<定期签入监视线程>”)
#
#监视器。添加监视功能(检查,1)
def gl1():
#使用time.sleep触发阻塞
log.info('在gl1处阻塞2秒')
时间。睡眠(2)
log.info('立即离开gl1')
def gl2():
#使用time.sleep触发阻塞
log.info('应检测到gl2处阻塞6秒')
时间。睡眠(6)
log.info('立即离开gl2')
def gl3():
#gevent.sleep不会阻塞
log.info('gl3不会被阻止,因为它使用了gevent.sleep')
gevent.睡眠(8)
log.info('立即离开gl3')
gevent.joinall([
gevent.spawn(gl3),
gevent.spawn(gl1),
gevent.spawn(gl2),
])

我希望有帮助

运行线程的堆栈跟踪?你是说跑绿茵场吗?如果是这样:gevent中没有线程,您应该尝试为这些gevent设置一个超时?gevent绿色线程称为线程-它们只是用户空间线程,而不是操作系统线程。对不起,我不确定这是如何解决这个问题的,因为它假设我正在手动跟踪哪些线程已经启动。好吧,你可以用一个超时来包装你的作业。确保它们都没有“旋转”。还有其他方法可以检测绿色let是否阻塞