【问题标题】:Wait for db future to complete?等待 db future 完成?
【发布时间】:2019-03-02 17:59:48
【问题描述】:

我已经为 sanic 应用程序编写了代码,rethinkdb 被用作后端数据库。我想等待 rethinkdb 连接函数在其他函数之前初始化,因为它们依赖于 rethinkdb 连接。

我的rethinkdb连接初始化函数是:

async def open_connections(app):
   logger.warning('opening database connection')
   r.set_loop_type('asyncio')
   connection= await r.connect(
       port=app.config.DATABASE["port"],
       host=app.config.DATABASE["ip"],
       db=app.config.DATABASE["dbname"],
       user=app.config.DATABASE["user"],
       password=app.config.DATABASE["password"])
   print (f"connection established {connection}")
   return connection

future解决后执行的回调函数是

def db_callback(future):
        exc = future.exception()
        if exc:
            # Handle wonderful empty TimeoutError exception
            logger.error(f"From mnemonic api isnt working with error {exc}")
            sys.exit(1)

        result = future.result()
        return result

sanic 应用程序:

def main():
        app = Sanic(__name__)
        load_config(app)
        zmq = ZMQEventLoop()
        asyncio.set_event_loop(zmq)
        server = app.create_server(
            host=app.config.HOST, port=app.config.PORT, debug=app.config.DEBUG, access_log=True)
        loop = asyncio.get_event_loop()

        ##not wait for the server to strat, this will return a future object
        asyncio.ensure_future(server)

        ##not wait for the rethinkdb connection to initialize, this will return
        ##a future object
        future = asyncio.ensure_future(open_connections(app))
        result = future.add_done_callback(db_callback)
        logger.debug(result)

        future = asyncio.ensure_future(insert_mstr_account(app))
        future.add_done_callback(insert_mstr_acc_callback)


        future = asyncio.ensure_future(check_master_accounts(app))
        future.add_done_callback(callbk_check_master_accounts)

        signal(SIGINT, lambda s, f: loop.close())


        try:
            loop.run_forever()
        except KeyboardInterrupt:
            close_connections(app)
            loop.stop()

当我启动这个应用程序时,open_connections 函数中的打印语句在最后执行。

【问题讨论】:

    标签: python-3.x async-await python-asyncio sanic


    【解决方案1】:
    future = asyncio.ensure_future(open_connections(app))
    result = future.add_done_callback(db_callback)
    

    ensure_future同时调度协程

    add_done_callback 不等待未来的完成,而是在未来完成后简单地安排一个函数调用。可以看here

    所以你应该在执行其他功能之前明确地await open_connections 未来:

    future = asyncio.ensure_future(open_connections(app))
    future.add_done_callback(db_callback)
    result = await future
    

    已编辑:以上答案仅适用于协程

    在这种情况下,我们要在函数体中等待future的完成。为此,我们应该使用loop.run_until_complete

    def main():
        ...
        future = asyncio.ensure_future(open_connections(app))
        future.add_done_callback(db_callback)
        result = loop.run_until_complete(future)
    

    【讨论】:

    • 什么都没有改变,rethinkdb 的初始化仍然在最后完成。
    • 我认为 await 的全部意义在于它将控制权传递回事件循环。
    • 是的,但它也会暂停等待对象上的协程执行,直到它完成
    • 抱歉,我没有注意到我们调用open connections 不是在协程中。我要编辑我的答案
    • @sauravverma 我已经补充了答案
    猜你喜欢
    • 2018-09-22
    • 2020-01-14
    • 1970-01-01
    • 1970-01-01
    • 2016-04-13
    • 2017-09-30
    • 1970-01-01
    • 1970-01-01
    • 2017-08-03
    相关资源
    最近更新 更多