Ответ
Основное различие заключается в том, как они обрабатывают блокирующие операции ввода-вывода (I/O) и как это влияет на производительность сервера.
Синхронный обработчик (def)
Это обычная функция Python. Когда она выполняет блокирующую операцию (например, запрос к базе данных, чтение файла, HTTP-запрос с помощью requests), она останавливает выполнение и ждет результата.
Чтобы это не блокировало весь сервер, FastAPI выполняет синхронные функции в отдельном пуле потоков (thread pool). Это позволяет основному циклу событий (event loop) продолжать обрабатывать другие запросы, пока текущий ожидает в своем потоке.
Когда использовать:
- Для CPU-bound задач (тяжелые вычисления).
- При использовании библиотек, у которых нет
asyncверсии (например, стандартные ORM илиrequests).
Пример:
import time
from fastapi import FastAPI
app = FastAPI()
@app.get("/sync-route")
def sync_route():
# Блокирующая операция: поток будет "спать" 2 секунды
time.sleep(2)
return {"message": "Done sleeping!"}
Асинхронный обработчик (async def)
Это корутина (coroutine), которая выполняется непосредственно в цикле событий. Когда она встречает await на I/O-операции (например, await async_db.fetch()), она передает управление обратно циклу событий, который может в это время выполнять другие задачи. После завершения I/O-операции выполнение корутины возобновляется.
Это более эффективный способ обработки множества одновременных I/O-запросов, так как не требует создания отдельных потоков для каждого.
Когда использовать:
- Для I/O-bound задач (работа с сетью, базами данных, файловой системой).
- При использовании
async-совместимых библиотек (httpx,asyncpg,aiofiles).
Пример:
import asyncio
from fastapi import FastAPI
app = FastAPI()
@app.get("/async-route")
async def async_route():
# Неблокирующая операция: цикл событий не блокируется
await asyncio.sleep(2)
return {"message": "Done sleeping asynchronously!"}
Ключевой вывод
- Используйте
async defдля операций ввода-вывода сasync-библиотеками для максимальной производительности. - Используйте
defдля процессорных задач или при работе с блокирующими библиотеками. FastAPI позаботится о том, чтобы они не блокировали сервер.
Ответ 18+ 🔞
А, слушай, тут народ часто путается, какую хуйню писать в роутах — def или async def. Ёпта, а разница-то проще, чем кажется, но от неё пиздец как зависит, как сервер будет ебашить.
Синхронный обработчик (def)
Ну, это обычная функция, как в старые добрые времена. Представь: она делает запрос к базе данных или читает файл — и на этом месте она встаёт как вкопанная и ждёт, пока эта операция не выполнится. Прям как мудак в очереди за сосиской в тесте.
Чтобы из-за одного такого тормоза не встал весь сервер, FastAPI берёт и кидает эту функцию в отдельный поток (thread pool). Пока один поток спит, главный цикл событий (event loop) может спокойно обслуживать других клиентов. Хитро, да?
Когда это юзать:
- Когда у тебя задачи, которые жрут процессор (CPU-bound) — типа сложных вычислений.
- Когда ты используешь библиотеки, которые нихуя не умеют в асинхронность (например, старый добрый
requestsили многие ORM).
Пример, чтобы было понятно:
import time
from fastapi import FastAPI
app = FastAPI()
@app.get("/sync-route")
def sync_route():
# Вот тут поток просто уснёт на 2 секунды, как сурок
time.sleep(2)
return {"message": "Done sleeping!"}
Асинхронный обработчик (async def)
А вот это уже корутина, мать её. Она работает прямо в цикле событий. Когда она доходит до операции ввода-вывода и видит await (например, await async_db.fetch()), она не тупо ждёт, а говорит: «Окей, я пока пошла, разбудите, когда данные придут». И цикл событий в это время может заниматься другими делами. Эффективность, блядь, зашкаливает!
Когда это юзать:
- Для всех операций, где ты ждёшь ответа от кого-то (I/O-bound) — запросы в сеть, базы, файлы.
- Когда у тебя есть асинхронные библиотеки (
httpx,asyncpg,aiofiles).
Пример для ясности:
import asyncio
from fastapi import FastAPI
app = FastAPI()
@app.get("/async-route")
async def async_route():
# Тут цикл событий не блокируется, он пойдёт делать другие дела
await asyncio.sleep(2)
return {"message": "Done sleeping asynchronously!"}
Так что же в итоге, ёпта?
async def— твой выбор, когда нужно ебашить кучу I/O-операций и есть подходящие библиотеки. Производительность будет овердохуищная.def— используй для тяжёлых вычислений или когда библиотека только синхронная. FastAPI сам разберётся и не даст ей заблокировать всё нахуй.
Вот и вся магия, никакой ебалы с мантрами.