Ждать дБ будущего, чтобы завершить? - PullRequest
0 голосов
/ 27 сентября 2018

Я написал код для приложения 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

Функция обратного вызова, которая будетвыполняется после разрешения будущего

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 app:

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()

Когда я запускаю это приложение, оператор print в функциях open_connections выполняется последним.

1 Ответ

0 голосов
/ 27 сентября 2018
future = asyncio.ensure_future(open_connections(app))
result = future.add_done_callback(db_callback)

ensure_future одновременно планирует сопрограммы

add_done_callback не ожидает завершения будущего, вместо этого он просто планирует вызов функции после завершения будущего.Вы можете видеть это здесь

Таким образом, вы должны явно ожидать open_connections будущее, прежде чем выполнять другие функции:

future = asyncio.ensure_future(open_connections(app))
future.add_done_callback(db_callback)
result = await 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)
...