什么是平均产量无(tornado.gen.moment)

时间:2017-07-25 10:21:08

标签: python-3.x tornado

我的Web应用程序中需要异步子进程锁。 我写下一个代码:

r = redis.Redis('localhost')
pipe = r.pipeline()
is_locked = False
while not is_locked:
    try:
        pipe.watch(lock_name)
        current_locked = int(pipe.get(lock_name))

        if current_locked == 0:
            pipe.multi()
            pipe.incr(lock_name)
            pipe.execute()
            is_locked = True
        else:
            yield None
    except redis.WatchError:
        yield None
return True

在编写的文档中,tornado.gen.moment(版本4.5以来的yield None)是一个特殊的对象,可以让IOLoop运行一次迭代。这个怎么运作?是否与其他Feature对象(来自其他请求)进行下一次迭代?这是正确的yield None用法吗?

1 个答案:

答案 0 :(得分:2)

gen.moment刚刚解决了使用回调添加到ioloop的Future对象。这允许运行ioloop的一次迭代。

使用协程的gen.Runner中的convert_yieldedyield None转换为gen.moment

每次迭代的ioloop(基本上是while True)都会执行以下操作:

  1. 使用ioloop的add_callbackadd_callback_from_signal

  2. 运行回调计划
  3. 使用ioloop的add_timeout

  4. 运行回调计划
  5. 轮询fd事件(例如,等待文件descirptor准备好写入或读取)。当然,为了不阻止ioloop,民意调查已超时。

  6. 运行ready fds的处理程序

  7. 因此,到达yield gen.moment点将允许一次完成上述所有事情(一次迭代)。

    作为示例,让我们安排异步任务 - 需要运行ioloop的httpclient fetch。另一方面,还会有阻塞功能(time.sleep)。

    import time
    from tornado import gen
    from tornado.ioloop import IOLoop
    from tornado.httpclient import AsyncHTTPClient
    
    
    @gen.coroutine
    def fetch_task():
        client = AsyncHTTPClient()
        yield client.fetch('http://google.com')
        print('fetch_task finished')
    
    
    @gen.coroutine
    def blocking():
        start_time = time.time()
        counter = 1 
        while True:
            time.sleep(5)
            print('blocking for %f' % (time.time() - start_time))
            yield gen.moment
            print('gen.moment counter %d' % counter)
            counter += 1
    
    
    @gen.coroutine
    def main():
        fetch_task()
        yield blocking()
    
    
    IOLoop.instance().run_sync(main)
    

    观察:

    • 没有yield gen.momentfetch_task将无法完成
    • time.sleep的增加/减少值不会影响完成fetch_task的ioloop所需的迭代次数。这也意味着AsyncHTTPClient.fetchN + 1(gen.moments +任务计划)与ioloop的交互(处理回调,轮询fd,处理事件)。
    • gen.moment并不总是意味着,其他任务将完成,而是让他们有机会更接近完成。