#python-asyncio
Вопрос:
Во время изучения asyncio я допустил ошибку и трижды сделал ссылку на переменную «task1».
import asyncio import time async def say_after(delay, what): await asyncio.sleep(delay) print(what) async def main(): print(f"start at {time.strftime('%X')}") task1 = asyncio.create_task(say_after(1, 'a')) task1 = asyncio.create_task(say_after(2, 'aba')) task1 = asyncio.create_task(say_after(3, 'faf')) await task1 #await task2 print(f"finished at {time.strftime('%X')}") asyncio.run(main())
Но когда я запустил код, я получил этот вывод
start at 19:05:19 a aba faf finished at 19:05:22
Почему он не печатает только последнюю созданную задачу? Почему первое и второе задания не очищаются?
На понятном python, если я напишу что-то вроде этого:
page = 0 page = 1 page = 2 print(page)
Я получу «2», потому что предыдущие ссылки на объекты будут удалены из памяти.
Почему там все по-другому? Как это работает?
Ответ №1:
Вы начинаете выполнять три задачи и ждете, пока завершится самая медленная из трех.
await task1
не выполняется задача, она ожидает завершения третьего объекта задачи, назначенного для task1
завершения. Две другие задачи все еще существуют в цикле событий и все еще выполняются, они заканчиваются первыми, потому что они быстрее.
Другой способ взглянуть на это — немного изменить свой код. Это сделает то, с чего вы ожидаете начать, а затем выдаст ошибки, потому что программа завершится раньше более медленных задач.
task1 = asyncio.create_task(say_after(3, 'a')) # make slowest task1 = asyncio.create_task(say_after(2, 'aba')) task1 = asyncio.create_task(say_after(1, 'faf')) # make fastest
Переписывание кода task1=
-это полное удаление, чтобы было ясно, что await task1
это больше связано с ожиданием завершения задачи и мало связано с ее запуском.
asyncio.create_task(say_after(1, 'a')) asyncio.create_task(say_after(2, 'aba')) asyncio.create_task(say_after(3, 'faf')) while len(asyncio.all_tasks()) gt; 1: await asyncio.sleep(0.1) # await task1
Более обычный способ — собрать ссылки на все задачи и дождаться завершения списка задач.
tasks = [] tasks.append(asyncio.create_task(say_after(3, 'a'))) tasks.append(asyncio.create_task(say_after(2, 'aba'))) tasks.append(asyncio.create_task(say_after(1, 'faf'))) await asyncio.gather(*tasks)