代码之家  ›  专栏  ›  技术社区  ›  GraphicalDot

等待db future完成?

  •  1
  • GraphicalDot  · 技术社区  · 6 年前

    我已经为sanic应用程序编写了一个代码,数据库被用作后端数据库。我想在其他函数依赖于reinspectdb connection之前等待reinspectdb connection函数初始化。

    我的DB连接初始化功能是:

    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\u connections函数中的print语句在最后一次执行。

    1 回复  |  直到 6 年前
        1
  •  2
  •   Artemiy Rodionov    6 年前
    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)