Правильно используя loop.create_future - PullRequest
0 голосов
/ 20 января 2019

Я читал документацию по Python и книгу PyMotW , пытаясь изучить Async / Await, Futures и Tasks.

Документация сопрограмм и задач :

Обычно нет необходимости создавать объекты Future на коде уровня приложения.

Из будущей документации говорится следующее:

loop.create_future ()

Создание объекта asyncio.Future, присоединенного к циклу событий.

Это предпочтительный способ создания фьючерсов в asyncio.Это позволяет сторонним циклам событий предоставлять альтернативные реализации объекта Future (с лучшей производительностью или инструментарием).

Однако в главе PyMotW о Future автор создает future объект, подобный этому:

all_done = asyncio.Future()

Я предполагаю, потому что книга немного отстает от текущей версии Python.Чтобы исправить это, я сделал следующее:

future_Obj = event_loop.create_future()

Таким образом, полный код авторов становится:

import asyncio


def mark_done(future, result):
    print('setting future result to {!r}'.format(result))
    future.set_result(result)


event_loop = asyncio.get_event_loop()

try:

    future_Obj = event_loop.create_future()
    print('scheduling mark_done')
    event_loop.call_soon(mark_done, future_Obj, 'the result')

    print('entering event loop')
    result = event_loop.run_until_complete(future_Obj)
    print('returned result: {!r}'.format(result))
finally:
    print('closing event loop')
    event_loop.close()

print('future result: {!r}'.format(future_Obj.result()))

Вопрос:

Есть future_Obj = event_loop.create_future() в приведенном выше примере, правильный способ создания объекта future в соответствии с документацией?

1 Ответ

0 голосов
/ 20 января 2019

Является ли future_Obj = event_loop.create_future() в приведенном выше примере правильным способом создания будущего объекта в соответствии с документацией?

Да, в коде, как показано, это именно такчтобы сделать это.

Следует обратить внимание на то, что будущее связано с циклом событий, поэтому создание будущего на верхнем уровне создает будущее, связанное с циклом, который asyncio.get_event_loop() возвращает изначально.Как только вы переключитесь на asyncio.run, вы получите ошибку, потому что каждый вызов asyncio.run создает новый цикл событий.

Чтобы избежать этой проблемы, может начаться будущее верхнего уровняотключите как None и создайте внутри сопрограммы, используя global в зависимости от ситуации.И поскольку вы явно передаёте будущее (что является хорошей практикой), вам вообще не нужна глобальная переменная:

def mark_done(future, result):
    print('setting future result to {!r}'.format(result))
    future.set_result(result)

async def main():
    loop = asyncio.get_event_loop()
    future = loop.create_future()
    print('scheduling mark_done')
    loop.call_soon(mark_done, future, 'the result')
    print('suspending the coroutine')
    result = await future
    print('awaited result: {!r}'.format(result))
    print('future result: {!r}'.format(future.result()))
    return result

if __name__ == '__main__':
    print('entering the event loop')
    result = asyncio.run(main())
    print('returned result: {!r}'.format(result))

Обратите внимание, что при использовании asyncio.run вам никогда не понадобитсяявно закрыть цикл, что делается автоматически.Если вы используете Python 3.6 или более раннюю версию, вы можете заменить asyncio.run(main()) на asyncio.get_event_loop().run_until_complete(main()).

...