【问题标题】:What my code needs a gen.sleep to execute a function async?我的代码需要 gen.sleep 来执行异步函数吗?
【发布时间】:2017-07-20 20:46:47
【问题描述】:

我有以下基于 Python 的 Tornado 编写的代码:

def process_data(data):
    # To something

def handler(message):
    if message['type'] == 'message':
        data = message['data']
        IOLoop.current().spawn_callback(process_data, data)

async def main():
    redis_client = RedisClient(redis_conf)
    pubsub = redis_client.subscribe("CHANNEL", handler)

    async def fetch_messages():
        while True:
            pubsub.get_message()
            await gen.sleep(0.0001) 


    await fetch_messages()

if __name__ == "__main__":
    import logging
    logging.basicConfig()

    parse_command_line()

    tornado.web.Application(debug=options.debug)

    io_loop = ioloop.IOLoop.current()
    io_loop.run_sync(main)

鉴于上面的代码,我可以看到 process_data 正在被调用。但是,如果我删除 await gen.sleep(0.0001),则永远不会调用 process_data。有谁知道为什么?

【问题讨论】:

    标签: python asynchronous tornado python-asyncio tornado-redis


    【解决方案1】:

    IOLoop.spawn_callback(callback, *args, **kwargs)

    在下一次 IOLoop 迭代中调用给定的回调

    如果您一直调用一些同步代码(while True 没有 await),您不会将控制权返回给事件循环,并且事件循环不能使其迭代执行回调。

    await gen.sleep(0.0001) 行 - 是控件返回事件循环的地方,以便它可以执行某些操作(例如执行回调)。

    Tornado 有特殊对象可以将控制权返回给事件循环,例如您的情况 - gen.moment:

        while True:
            pubsub.get_message()
            await gen.moment
    

    我没有使用 Tornado,但我敢打赌,使用一些设计用于异步程序的 redis 客户端会更好,see this answer

    【讨论】:

      猜你喜欢
      • 2018-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多