Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Изучение aiogram: От нуля до production-ready бота
aiogram — один из самых популярных фреймворков для разработки Telegram ботов на Python. Я изучал его систематически, начиная с основ и постепенно переходя к сложным паттернам. Вот мой путь обучения.
Фаза 1: Основы и первый bot (1-2 недели)
Начал с официальной документации и простых примеров.
# Мой первый бот на aiogram 3.x
from aiogram import Bot, Dispatcher, F
from aiogram.types import Message
from aiogram.filters import Command
from aiogram.fsm.context import FSMContext
import logging
import asyncio
# Инициализация
TOKEN = "YOUR_TOKEN_HERE"
bot = Bot(token=TOKEN)
dp = Dispatcher()
# Простой handler на команду /start
@dp.message(Command("start"))
async def start_command(message: Message):
await message.answer(f"Привет, {message.from_user.full_name}!")
# Echo бот для всех сообщений
@dp.message()
async def echo(message: Message):
await message.answer(f"Вы написали: {message.text}")
# Запуск
async def main():
await dp.start_polling(bot)
if __name__ == "__main__":
asyncio.run(main())
Что я сразу изучил:
- Установка и настройка (
pip install aiogram) - Bot API token и его безопасность
- Базовые обработчики (handlers)
- Асинхронность в Python (async/await)
- Структура диспетчера (Dispatcher)
Фаза 2: FSM и состояния (1-2 недели)
Переход к более сложным ботам с сохранением состояния пользователя.
from aiogram.fsm.state import State, StatesGroup
from aiogram.fsm.context import FSMContext
from aiogram.types import ReplyKeyboardMarkup, KeyboardButton, Message
# Определяю состояния
class Form(StatesGroup):
waiting_for_name = State() # Ожидаем имя
waiting_for_age = State() # Ожидаем возраст
waiting_for_email = State() # Ожидаем email
waiting_for_confirmation = State() # Подтверждение
# Фильтр для файлов состояния
from aiogram.fsm.storage.memory import MemoryStorage
# В production используем Redis
# Начало регистрации
@dp.message(Command("register"))
async def start_registration(message: Message, state: FSMContext):
await state.set_state(Form.waiting_for_name)
await message.answer("Введите ваше имя:")
# Обработка имени
@dp.message(Form.waiting_for_name)
async def process_name(message: Message, state: FSMContext):
await state.update_data(name=message.text)
await state.set_state(Form.waiting_for_age)
await message.answer("Спасибо! Теперь укажите ваш возраст:")
# Обработка возраста
@dp.message(Form.waiting_for_age)
async def process_age(message: Message, state: FSMContext):
try:
age = int(message.text)
if age < 13:
await message.answer("Возраст должен быть от 13 лет")
return
await state.update_data(age=age)
await state.set_state(Form.waiting_for_email)
await message.answer("Укажите ваш email:")
except ValueError:
await message.answer("Введите корректный возраст (число)")
# Завершение
@dp.message(Form.waiting_for_email)
async def process_email(message: Message, state: FSMContext):
data = await state.get_data()
# Сохраняю в БД
await message.answer(
f"Спасибо за регистрацию, {data['name']}!"
)
await state.clear() # Очищаю состояние
Ключевые концепции:
- FSM (Finite State Machine) для сложных сценариев
- Сохранение контекста пользователя
- Валидация на каждом шаге
- В production использую Redis вместо MemoryStorage
Фаза 3: Inline кнопки и Callback Query (1-2 недели)
Изучал интерактивные кнопки для лучшего UX.
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton
from aiogram.types import CallbackQuery
class ItemsCallback(BaseModel): # Typed CallbackData
action: str
item_id: int
# Отправка сообщения с кнопками
@dp.message(Command("menu"))
async def show_menu(message: Message):
kb = InlineKeyboardMarkup(inline_keyboard=[
[InlineKeyboardButton(text="Заказать", callback_data="order")],
[InlineKeyboardButton(text="Помощь", callback_data="help")],
[InlineKeyboardButton(text="О нас", callback_data="about")],
])
await message.answer("Выберите опцию:", reply_markup=kb)
# Обработка нажатия кнопки
@dp.callback_query(F.data == "order")
async def process_order(callback: CallbackQuery):
await callback.answer("Вы выбрали заказ!") # Уведомление
await callback.message.edit_text(
"Оформление заказа...",
reply_markup=None # Удаляю кнопки
)
# Typed CallbackData (рекомендуемый подход)
class ProductCallback(BaseModel):
action: str # 'buy' или 'info'
product_id: int
@dp.callback_query(F.data.startswith("product_"))
async def handle_product(callback: CallbackQuery):
data = callback.data.split("_")[1]
product_id = int(data)
# Обработка...
Фаза 4: Работа с БД и middlewares (2 недели)
Интеграция с реальной базой данных и логирование.
from sqlalchemy.orm import Session
from typing import Callable, Dict, Any
from aiogram.middlewares.base import BaseMiddleware
# Middleware для логирования
class LoggingMiddleware(BaseMiddleware):
async def __call__(
self,
handler: Callable[[Message, Dict[str, Any]], Any],
event: Message,
data: Dict[str, Any]
) -> Any:
print(f"Message from {event.from_user.id}: {event.text}")
return await handler(event, data)
# Регистрирую middleware
dp.message.middleware(LoggingMiddleware())
# Middleware для подключения к БД
class DatabaseMiddleware(BaseMiddleware):
def __init__(self, db_session_maker):
self.db_session_maker = db_session_maker
async def __call__(
self,
handler: Callable,
event: Message,
data: Dict[str, Any]
) -> Any:
async with self.db_session_maker() as session:
data['session'] = session
return await handler(event, data)
# Использование
@dp.message()
async def echo(message: Message, session: Session):
user = session.query(User).filter(
User.telegram_id == message.from_user.id
).first()
if not user:
user = User(telegram_id=message.from_user.id)
session.add(user)
session.commit()
await message.answer(f"Привет, {user.username}!")
Фаза 5: Advanced паттерны и production (3+ недели)
Фильтры и правила маршрутизации
from aiogram.filters import BaseFilter
class IsAdmin(BaseFilter):
async def __call__(self, message: Message) -> bool:
return message.from_user.id in ADMIN_IDS
# Использование
@dp.message(IsAdmin(), Command("admin_panel"))
async def admin_panel(message: Message):
await message.answer("Админ панель")
Обработка ошибок
from aiogram.filters import ExceptionTypeFilter
from aiogram.types import Update
@dp.error(ExceptionTypeFilter(Exception))
async def error_handler(update: Update, error: Exception):
logging.error(f"Update {update.update_id} caused error: {error}")
# Отправляю уведомление админу
# Логирую в файл или сервис мониторинга
Webhook вместо polling
from fastapi import FastAPI
from aiogram.types import Update
app = FastAPI()
@app.post("/webhook")
async def webhook(update: dict):
await dp.feed_update(bot, Update(**update))
return {"ok": True}
Ресурсы, которые помогли
- Официальная документация: https://docs.aiogram.dev/ — всегда начинаю отсюда
- Примеры на GitHub:
aiogram/aiogramrepository - Telegram Bot API docs: https://core.telegram.org/bots/api
- Сообщество: @aiogram_ru, Stack Overflow
- Собственные проекты: Практика — лучший учитель
Типичные ошибки, которые я делал
- Забывал await перед async функциями → много багов с race conditions
- Использовал MemoryStorage в production → данные теряются при перезагрузке
- Не обрабатывал ошибки → боты падали без логирования
- Hardcodил токены в коде → проблемы с безопасностью
- Не использовал файлы состояния → запутанный код с глобальными переменными
Современные best practices (aiogram 3.x)
- Используй Typed CallbackData вместо строк
- FSM для UI-state только, не для бизнес-логики
- Middleware для кросс-функционального функционала
- Dependency injection для инъекции сервисов
- Webhook в production, polling только для разработки
- Graceful shutdown перед обновлением
Итог
Обучение aiogram — это не просто чтение документации, это практика через реальные проекты. Я начал с простого echo бота, потом добавлял FSM, БД, сложные UI. Каждый проект учил меня новому: async patterns, обработка ошибок, масштабирование. Сейчас я могу быстро писать production-ready Telegram ботов с любой сложностью.