41. (П20) Налагодження асинхронного коду та робота з подійним циклом¶
Передумови¶
- Прочитана Лекція 40 — Проблеми виконання асинхронного коду, ручне керування подійним циклом та налагодження asyncio
- Python 3.11+
Персоналізація
У кожному файлі оголосіть константу STUDENT = "Imya Prizvysche" (ваші дані латиницею) і виводьте її у першому рядку кожного запуску програми: print(f"Student: {STUDENT}"). На скріншотах у звіті повинно бути видно ваше ім'я.
Завдання¶
Виконати дві невеликі програми, які демонструють базові навички налагодження asyncio і ручного керування event loop.
Частина 1: знайти і виправити повільний крок¶
Файл slow_step.py.
Оголосіть три корутини:
| Корутина | Поведінка |
|---|---|
load() |
друкує "load: start", чекає 0.3с через asyncio.sleep, повертає "raw" |
process() |
друкує "process: start", викликає time.sleep(1.2), повертає "clean" |
save() |
друкує "save: start", чекає 0.5с через asyncio.sleep, нічого не повертає |
Оголосіть корутину step(name, coro), яка:
- запам'ятовує час через
time.perf_counter; - чекає
coroчерезawait; - друкує
f"[{name}] {elapsed:.2f}s"; - повертає результат корутини.
У main послідовно викличте всі три кроки через step("load", ...), step("process", ...), step("save", ...). Запустіть через asyncio.run(main(), debug=True).
Очікуваний вивід:
У debug-режимі asyncio додатково попередить про повільний callback у process (took ... seconds).
Виправлення. Зробіть так, щоб process не блокувала event loop: оберніть time.sleep(1.2) у asyncio.to_thread. Запустіть програму ще раз і переконайтесь, що попередження зникло.
У звіті у 1 реченні поясніть, чому до виправлення asyncio попереджав про повільний callback саме у process, а не у load чи save.
Частина 2: ручне керування event loop¶
Файл manual_loop.py.
Оголосіть корутину tick():
- у нескінченному циклі друкує
f"tick {i}"(деi— лічильник з 1); - чекає 1 секунду через
asyncio.sleep; - у блоці
except asyncio.CancelledErrorдрукує"tick: stopped"і робитьraise.
У main (звичайна синхронна функція):
- створіть новий event loop через
asyncio.new_event_loop(); - зареєструйте задачу через
loop.create_task(tick()); - запустіть
loop.run_forever()у блоціtry; - у
except KeyboardInterruptскасуйте задачу черезtask.cancel()і викличтеloop.run_until_complete(task)(огорніть уtry/except CancelledError); - у
finallyвикличтеloop.close()і надрукуйте"loop closed".
Запустіть програму, дайте їй надрукувати 3-4 тіки і натисніть Ctrl+C.
Очікуваний вивід (приблизно):
У звіті у 1-2 реченнях поясніть, навіщо ми викликаємо loop.run_until_complete(task) після task.cancel() — що було б, якби ми просто закрили loop одразу.
Результат¶
Після виконання роботи здайте звіт зі скріншотами:
- Частина 1: вивід
slow_step.pyдо і після виправлення (з попередженням asyncio і без нього); пояснення, чому попереджало саме проprocess - Частина 2: вивід
manual_loop.pyіз зупинкою черезCtrl+C; пояснення роліrun_until_completeпісля скасування
Знайшли помилку чи бажаєте додати інформацію, щоб покращити курс? Створіть issue на GitHub