Ответ
До появления ключевых слов async/await в Python 3.5, асинхронность на базе asyncio реализовывалась с помощью генераторов и специального декоратора.
Основными инструментами были:
- Декоратор
@asyncio.coroutine: Он помечал функцию-генератор как корутину, совместимую с циклом событийasyncio. - Выражение
yield from: Использовалось вместо современногоawaitдля передачи управления другой корутине и ожидания её результата.
По сути, async def является синтаксическим сахаром над генераторами, а await — над yield from.
Сравнение синтаксиса:
Старый стиль (Python 3.4):
import asyncio
@asyncio.coroutine
def old_style_fetch_data(url):
print(f"Fetching {url}...")
# Вместо await используется yield from
response = yield from asyncio.sleep(1) # Имитация сетевого запроса
print(f"Done fetching {url}.")
return {"data": f"Some data from {url}"}
loop = asyncio.get_event_loop()
loop.run_until_complete(old_style_fetch_data("https://example.com"))
Современный стиль (Python 3.5+):
import asyncio
async def new_style_fetch_data(url):
print(f"Fetching {url}...")
# Используется async/await
await asyncio.sleep(1)
print(f"Done fetching {url}.")
return {"data": f"Some data from {url}"}
asyncio.run(new_style_fetch_data("https://example.com"))
Основной недостаток старого подхода заключался в том, что синтаксически корутины не отличались от обычных генераторов, что могло приводить к путанице. Введение async/await сделало асинхронный код более явным и читаемым.
Ответ 18+ 🔞
Да ты посмотри, какая история-то, блядь! Прямо как в том анекдоте про Герасима, только про питон. Раньше-то, сука, чтобы асинхронность запилить, приходилось выкручиваться, как уж на сковородке.
Вот представь: Python 3.4, темные времена, async и await ещё не изобрели, а ебашить асинхронно уже охота. И что делали? Да хуй с горы, использовали генераторы, блядь! Самые обычные yield.
Главными инструментами были два страдальца:
- Декоратор
@asyncio.coroutine. Этой хуйней обмазывали функцию-генератор, чтобы цикл событий понял — о, это корутина, её можно ебашить. - Выражение
yield from. Вместо красивогоawaitприходилось городить эту конструкцию, чтобы передать управление и ждать, пока другая корутина свои дела сделает.
По сути, весь этот новый красивый синтаксис — это просто синтаксический сахар, намазанный на старые добрые генераторы. async def — это обёртка, а await — это yield from, только в цилиндре.
Смотри, как раньше мучались (Python 3.4):
import asyncio
@asyncio.coroutine
def old_style_fetch_data(url):
print(f"Fetching {url}...")
# Вместо await используется yield from
response = yield from asyncio.sleep(1) # Имитация сетевого запроса
print(f"Done fetching {url}.")
return {"data": f"Some data from {url}"}
loop = asyncio.get_event_loop()
loop.run_until_complete(old_style_fetch_data("https://example.com"))
Видал? yield from! Прямо как немой Герасим мычит. "Му-му, отдай мне управление, блядь, и жди".
А теперь посмотри, как сейчас красиво (Python 3.5+):
import asyncio
async def new_style_fetch_data(url):
print(f"Fetching {url}...")
# Используется async/await
await asyncio.sleep(1)
print(f"Done fetching {url}.")
return {"data": f"Some data from {url}"}
asyncio.run(new_style_fetch_data("https://example.com"))
Во, ёпта! Чисто, понятно, сразу видно — асинхронная функция. А раньше-то вся проблема была, блядь, в том, что корутина с виду ни хуя не отличалась от простого генератора. Запутаться — раз плюнуть. Сейчас же всё явно, как божий день. В рот меня чих-пых, прогресс налицо!