Tornado的周期回调如果执行时间超过回调时间也不被跳过
考虑以下代码:
from tornado import ioloop, gen
@gen.coroutine
def test_callback():
print 'entering test_callback'
yield gen.sleep(10)
print 'exiting test_callback'
if __name__ == '__main__':
ioloop.PeriodicCallback(test_callback, 1000 * 5).start()
ioloop.IOLoop.current().start()
这是输出结果:
entering test_callback
entering test_callback
entering test_callback
exiting test_callback
entering test_callback
exiting test_callback
entering test_callback
...
文档中提到,如果回调函数的执行时间超过了设定的时间,那么后续的调用会被跳过。但是在这个例子中,并没有发生这种情况。我该怎么做才能确保回调函数只有在上一个调用完成后才会被调用呢?
相关文章:
- 暂无相关问题
2 个回答
0
下面这个基于 Python 3.5 的解决方案也可以使用。
from tornado import ioloop, httpclient
class testCls:
def __init__(self):
self.n=0
self.inProcess=False
async def f1(self):
url2='http://yoosofan.github.io/en/'
http_client1 = httpclient.AsyncHTTPClient()
response = await http_client1.fetch(url2)
print('dd: ',self.n)
self.n +=1
async def my_function(self):
print('z',end=' ')
if self.inProcess==False:
self.inProcess=True
await self.f1()
self.inProcess=False
if __name__ == '__main__':
t1=testCls()
ioloop.PeriodicCallback(t1.my_function, 60).start()
ioloop.IOLoop.current().start()
1
我在这个讨论串中找到了答案。
简单来说,如果一个回调函数执行的时间超过了设定的时间,那么后续的调用只有在这个回调是同步的情况下才会被跳过。如果这个回调又调用了另一个异步的程序,PeriodicCallback就无法知道所有的调用会开始另一个回调。
在这种情况下,我们需要一个支持异步的PeriodicCallback替代品:
from tornado import ioloop, gen
@gen.coroutine
def test_callback():
print 'entering test_callback'
yield gen.sleep(10)
print 'exiting test_callback'
@gen.coroutine
def periodic():
loop = ioloop.IOLoop.current()
while True:
start = loop.time()
yield test_callback()
duration = loop.time() - start
yield gen.Task(loop.add_timeout, max(5 - duration, 0))
if __name__ == '__main__':
ioloop.IOLoop.current().add_callback(periodic)
ioloop.IOLoop.current().start()
这是输出结果:
entering test_callback
exiting test_callback
entering test_callback
exiting test_callback
entering test_callback
exiting test_callback
...