Python asyncio: Як прискорити ваші програми за допомогою async/await
### Дізнайтеся, як асинхронне програмування в Python з asyncio та ключовими словами async/await може кардинально підвищити продуктивність ваших I/O-залежних застосунків. Цей посібник для початківців пояснює основи, демонструє переваги на практичних прикладах коду та розкриває типові помилки.
---
Чому звичайний код буває повільним? Уявіть, що ви готуєте сніданок. Ви ставите тости в тостер, а потім стоїте і чекаєте 2 хвилини, поки вони приготуються. Тільки після цього ви ставите чайник. Поки він кипить (ще 3 хвилини), ви знову чекаєте. І лише потім нарізаєте авокадо. Такий підхід називається **синхронним**: кожна дія виконується суворо одна за одною. А тепер уявіть ефективний підхід: ви ставите тости, одразу вмикаєте чайник, і поки вони обидва готуються, ви спокійно нарізаєте авокадо. Це — **асинхронний** підхід. Ви не витрачаєте час на очікування, а виконуєте інші завдання. У програмуванні все так само. Коли ваша програма робить запит до бази даних, звертається до API або завантажує файл з мережі, вона переважно просто чекає на відповідь. Це очікування називається I/O (Input/Output). Асинхронне програмування дозволяє вашій програмі не "завмирати" під час таких очікувань, а переключатися на інші корисні завдання. І в Python для цього існує потужний інструмент — бібліотека
asyncio.
Що таке
asyncio, async та await?
Це три кити, на яких тримається асинхронність у сучасному Python. Розберемося з кожним із них.
asyncio — менеджер завдань
asyncio — це стандартна бібліотека Python для написання асинхронного коду. Її серцем є **цикл подій (event loop)**. Це своєрідний диспетчер, який знає про всі ваші асинхронні завдання і вміло перемикається між ними. Коли одне завдання починає чекати (наприклад, відповіді від сервера), цикл подій призупиняє його і передає керування іншому завданню, яке готове до виконання.
async def — оголошення "паузибельної" функції
Звичайні функції в Python (def) не можна призупининити. Якщо ви її викликали, вона буде виконуватися до кінця.
Щоб створити функцію, яку цикл подій може призупиняти та відновлювати, її потрібно оголосити з ключовим словом async def. Такі функції називаються **корутинами (coroutines)**.
async def get_data_from_api():
# Ця функція є корутиною
print("Починаю запит до API...")
# Тут буде операція очікування
print("Запит завершено.")
return {"data": 123}
await — команда "почекай тут"
Ключове слово await можна використовувати тільки всередині async функцій. Воно робить дві речі:
1. Каже циклу подій: "Я зараз буду чекати на результат цієї операції. Вона може бути довгою".
2. Призупиняє виконання поточної корутини і дозволяє циклу подій запустити іншу.
Коли операція, на яку ми чекали, завершиться, цикл подій повернеться до нашої корутини і продовжить її виконання з того ж місця.
Синхронний vs Асинхронний код: Практичний приклад Найкращий спосіб зрозуміти різницю — побачити її на власні очі. Давайте змоделюємо завантаження трьох файлів, кожне з яких займає 1 секунду.
Синхронний підхід
Тут ми використовуємоtime.sleep(), щоб імітувати очікування.
import time
def download_file_sync(filename):
print(f"Починаю завантажувати {filename}...")
time.sleep(1) # Імітація довгого I/O очікування
print(f"{filename} завантажено.")
def main_sync():
start_time = time.time()
download_file_sync("file1.txt")
download_file_sync("file2.txt")
download_file_sync("file3.txt")
end_time = time.time()
print(f"Синхронне виконання зайняло {end_time - start_time:.2f} секунд.")
main_sync()
# Вивід:
# Починаю завантажувати file1.txt...
# file1.txt завантажено.
# Починаю завантажувати file2.txt...
# file2.txt завантажено.
# Починаю завантажувати file3.txt...
# file3.txt завантажено.
# Синхронне виконання зайняло 3.01 секунд.
Як і очікувалося, загальний час дорівнює сумі всіх очікувань: 1 + 1 + 1 ≈ 3 секунди.
Асинхронний підхід
Тепер використаємоasyncio. Замість time.sleep() ми візьмемо його асинхронний аналог asyncio.sleep().
import asyncio
import time
async def download_file_async(filename):
print(f"Починаю завантажувати {filename}...")
await asyncio.sleep(1) # Асинхронна пауза, не блокує інші завдання
print(f"{filename} завантажено.")
async def main_async():
start_time = time.time()
# Створюємо список завдань, але ще не чекаємо їх завершення
tasks = [
download_file_async("file1.txt"),
download_file_async("file2.txt"),
download_file_async("file3.txt"),
]
# Запускаємо всі завдання паралельно і чекаємо їх одночасного завершення
await asyncio.gather(*tasks)
end_time = time.time()
print(f"Асинхронне виконання зайняло {end_time - start_time:.2f} секунд.")
# Запускаємо головну асинхронну функцію
asyncio.run(main_async())
# Вивід:
# Починаю завантажувати file1.txt...
# Починаю завантажувати file2.txt...
# Починаю завантажувати file3.txt...
# file1.txt завантажено.
# file2.txt завантажено.
# file3.txt завантажено.
# Асинхронне виконання зайняло 1.01 секунд.
Результат вражає! Загальний час виконання склав трохи більше 1 секунди. Це тому, що всі три "очікування" відбувалися одночасно. asyncio запускав перше завдання, бачив await asyncio.sleep(1), призупиняв його, запускав друге, призупиняв, запускав третє. А через секунду вони всі одночасно "прокинулися" і завершилися.
Коли варто використовувати
asyncio?
Асинхронний підхід не є універсальним рішенням. Він ідеально підходить для **I/O-залежних (I/O-bound)** завдань, де програма багато часу проводить в очікуванні:
* **Веб-скрапінг та робота з API:** одночасне виконання сотень HTTP-запитів.
* **Мережеві сервери та чат-боти:** обробка тисяч одночасних з'єднань від клієнтів.
* **Робота з базами даних:** виконання запитів до БД, поки інші частини програми працюють.
* **Читання/запис файлів** з повільних дисків.
asyncio **не підходить** для **CPU-залежних (CPU-bound)** завдань, таких як складні математичні обчислення, обробка зображень чи архівування файлів. У таких випадках краще використовувати багатопроцесорність (multiprocessing).
Висновок Асинхронне програмування з
asyncio — це не магія, а потужний інструмент для оптимізації продуктивності Python-застосунків. Зрозумівши принципи роботи async def, await та циклу подій, ви зможете писати код, який виконує завдання, що пов'язані з очікуванням, у рази швидше. Це особливо важливо в сучасному світі, де майже кожна програма взаємодіє з мережею.
Почніть з малих експериментів, перепишіть невелику частину вашого I/O-залежного коду на async/await і виміряйте різницю. Результати вас приємно здивують.
Якщо у вас виникли запитання, потрібна консультація щодо оптимізації вашого проєкту або ви хочете обговорити співпрацю, не соромтеся писати мені на email: **isholegg@gmail.com**.
---
Ключові слова Python, asyncio, async, await, асинхронне програмування, корутини, event loop, оптимізація продуктивності, I/O-bound, веб-скрапінг, Python для початківців, паралельне виконання, non-blocking I/O.
Meta Детальний посібник з асинхронного програмування в Python. Дізнайтеся, як використовувати
asyncio, async та await для кардинального прискорення I/O-залежних задач, з простими поясненнями та практичними прикладами коду.Якщо у вас виникли питання, вбо ви бажаєте записатися на індивідуальний урок, замовити статтю (інструкцію) або придбати відеоурок, пишіть нам на: скайп: olegg.pann telegram, viber - +380937663911 додавайтесь у телеграм-канал: t.me/webyk email: oleggpann@gmail.com ми у fb: www.facebook.com/webprograming24 Обов`язково оперативно відповімо на усі запитіння
Поділіться в соцмережах
Подобные статьи:
