Почему запуск асинхронной сопрограммы не возвращает контроль? - PullRequest
0 голосов
/ 27 декабря 2018

У меня есть пример кода:

import asyncio

import time

async def asyncsleep(number):
    time.sleep(number)

async def do_one():
    await asyncsleep(1)
    print("one 1")
    await asyncsleep(1)
    print("one 2")
    await asyncsleep(1)
    print("one 3")

async def do_two():
    await asyncsleep(1)
    print("two 1")
    await asyncsleep(1)
    print("two 2")
    await asyncsleep(1)
    print("two 3")

loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait([
    do_one(),
    do_two()
]))
loop.close()

Ожидается, что в этом коде две функции будут работать параллельно.Я имею в виду, что выход обоих должен прийти одновременно.Но этого не происходит.Причина в том, что я сам реализовал функцию сна asyncsleep.Если я использую asyncio.sleep вместо него, все работает нормально.

import asyncio

import time

async def asyncsleep(number):
    time.sleep(number)

async def do_one():
    await asyncio.sleep(1)
    print("one 1")
    await asyncio.sleep(1)
    print("one 2")
    await asyncio.sleep(1)
    print("one 3")

async def do_two():
    await asyncio.sleep(1)
    print("two 1")
    await asyncio.sleep(1)
    print("two 2")
    await asyncio.sleep(1)
    print("two 3")

loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait([
    do_one(),
    do_two()
]))
loop.close()

Я также посмотрел подпись функции asyncio.sleep:

@coroutine
def sleep(delay, result=None, *, loop=None):
    """Coroutine that completes after a given time (in seconds)."""
    if delay == 0:
        yield
        return result

    if loop is None:
        loop = events.get_event_loop()
    future = loop.create_future()
    h = future._loop.call_later(delay,
                                futures._set_result_unless_cancelled,
                                future, result)
    try:
        return (yield from future)
    finally:
        h.cancel()

Что за asyncio.sleepфункция имеет, что моя реализованная asyncsleep функция не имеет?Они оба сопрограммы. Почему они ведут себя по-разному?

Ответы [ 2 ]

0 голосов
/ 28 декабря 2018

Async не является потоками.Асинхронный код не прекращает управление, пока не достигнет ожидающего или функция не завершитсяВаша функция сна не сдает управление, поэтому:

Работает асинхронный цикл, запланированы do_one и do_two.Цикл выбирает запуск do_one, и потому что вы не даете или не ждете, ваш код не возвращается в цикл, пока функция не завершится.

0 голосов
/ 27 декабря 2018

Когда вы делаете асинхронные вещи, у вас нет непрерывного потока.Существует цикл событий , который имеет пул задач и переключается между ними: когда текущая задача await с, цикл передает управление одной из других задач вбассейн.

time.sleep , как изящно указано в комментариях @ user2357112, является синхронным, он просто блокирует выполнение на некоторое время, не давая возможности перейти к другой сопрограмме.

Итак, что есть у asyncio.sleep, а у asyncsleep нет:

  • Создается новый Future (специальный объект, представляющий результат задачи, котораяеще не еще выполнено)
  • Эта новая задача ничего не делает, но занимает определенное время
  • Таким образом, новое время даст result, когда придет время
  • Эта задача помогает блокировать поток, в котором ожидался asyncio.sleep, но не блокирует другие задачи.

Почувствуйте разницу.

...