Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI30 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
SQLAlchemy: ORM для работы с базами данных
SQLAlchemy — это один из самых мощных инструментов для работы с БД в Python. Для Data Scientist это фундаментальный навык, так как большинство данных хранится в реляционных БД.
Что такое SQLAlchemy
SQLAlchemy — это ORM (Object-Relational Mapper) и SQL toolkit для Python, который:
- Отображает таблицы БД на классы Python (ORM)
- Позволяет писать SQL через Python код (Query Builder)
- Управляет соединениями с БД (Connection Pooling)
- Абстрагирует разные СУБД (PostgreSQL, MySQL, SQLite, Oracle)
Архитектура
┌─────────────────────────────────────┐
│ Приложение (Python код) │
├─────────────────────────────────────┤
│ SQLAlchemy ORM / Query Builder │ ← Вы работаете с этим
├─────────────────────────────────────┤
│ SQLAlchemy Core (Dialects) │ ← Абстракция БД
├─────────────────────────────────────┤
│ Python Database Drivers │ ← psycopg2, pymysql
├─────────────────────────────────────┤
│ PostgreSQL / MySQL / SQLite │ ← Реальная БД
└─────────────────────────────────────┘
Установка
pip install sqlalchemy
pip install psycopg2 # Для PostgreSQL
pip install pymysql # Для MySQL
Основные концепции
1. Engine — соединение с БД
from sqlalchemy import create_engine
# PostgreSQL
engine = create_engine(
'postgresql://user:password@localhost:5432/database_name'
)
# MySQL
engine = create_engine(
'mysql+pymysql://user:password@localhost:3306/database_name'
)
# SQLite (локальный файл)
engine = create_engine('sqlite:///database.db')
# Проверка соединения
with engine.connect() as conn:
result = conn.execute('SELECT 1')
print('Connection successful!')
2. Session — управление транзакциями
from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind=engine)
session = Session()
# Используем session для всех операций
try:
# Операции с БД
session.commit() # Сохраняем изменения
except Exception as e:
session.rollback() # Откатываем при ошибке
finally:
session.close() # Закрываем соединение
3. Declarative Base — ORM модели
from sqlalchemy import Column, Integer, String, Float, DateTime
from sqlalchemy.ext.declarative import declarative_base
from datetime import datetime
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
username = Column(String(50), unique=True, nullable=False)
email = Column(String(100), unique=True)
age = Column(Integer)
created_at = Column(DateTime, default=datetime.now)
def __repr__(self):
return f'User({self.username}, {self.email})'
class Purchase(Base):
__tablename__ = 'purchases'
id = Column(Integer, primary_key=True)
user_id = Column(Integer, ForeignKey('users.id'))
amount = Column(Float)
created_at = Column(DateTime, default=datetime.now)
Практические примеры
Пример 1: CRUD операции
from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind=engine)
session = Session()
# CREATE (создание)
new_user = User(
username='john_doe',
email='john@example.com',
age=30
)
session.add(new_user)
session.commit()
print(f'User created with id: {new_user.id}')
# READ (чтение)
user = session.query(User).filter_by(username='john_doe').first()
print(f'Found user: {user.username}, {user.email}')
# UPDATE (обновление)
user.age = 31
session.commit()
print(f'User age updated to {user.age}')
# DELETE (удаление)
session.delete(user)
session.commit()
print('User deleted')
session.close()
Пример 2: Сложные запросы (SQL эквивалент)
# SQL: SELECT * FROM users WHERE age > 25 ORDER BY username
users = session.query(User).filter(User.age > 25).order_by(User.username).all()
# SQL: SELECT username, email FROM users WHERE age BETWEEN 20 AND 30
users = session.query(User.username, User.email).filter(
User.age.between(20, 30)
).all()
# SQL: SELECT COUNT(*) FROM users
count = session.query(User).count()
# SQL: SELECT * FROM users WHERE username LIKE 'john%'
users = session.query(User).filter(User.username.like('john%')).all()
# SQL: SELECT * FROM users WHERE age IN (25, 30, 35)
users = session.query(User).filter(User.age.in_([25, 30, 35])).all()
Пример 3: JOIN операции
from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship
# Определяем отношение
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
username = Column(String(50))
purchases = relationship('Purchase', back_populates='user')
class Purchase(Base):
__tablename__ = 'purchases'
id = Column(Integer, primary_key=True)
user_id = Column(Integer, ForeignKey('users.id'))
amount = Column(Float)
user = relationship('User', back_populates='purchases')
# JOIN через relationship
user = session.query(User).filter_by(username='john').first()
print(f'User purchases: {user.purchases}') # Автоматический JOIN
# JOIN через query
result = session.query(User.username, Purchase.amount).join(Purchase).all()
# LEFT JOIN
result = session.query(User).outerjoin(Purchase).all()
Пример 4: Для Data Science (загрузка в Pandas)
import pandas as pd
from sqlalchemy import create_engine
engine = create_engine('postgresql://user:pass@localhost/db')
# Способ 1: Прямое чтение в DataFrame
df = pd.read_sql(
'SELECT * FROM users WHERE age > 25',
engine
)
print(df.head())
# Способ 2: Через SQLAlchemy Query
from sqlalchemy.orm import Session
with Session(engine) as session:
query = session.query(User).filter(User.age > 25)
df = pd.read_sql(
query.statement, # Преобразуем Query в SQL statement
engine
)
# Способ 3: Полностью через Pandas
df = pd.read_sql_table('users', engine) # Читает всю таблицу
# Сохранение обратно в БД
df.to_sql('processed_users', engine, if_exists='replace', index=False)
Пример 5: Полный ML pipeline с SQLAlchemy
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
engine = create_engine('postgresql://user:pass@localhost/ml_db')
# 1. Загрузка данных из БД
df = pd.read_sql(
'SELECT * FROM training_data WHERE is_valid = true',
engine
)
print(f'Loaded {len(df)} records')
# 2. Подготовка данных
X = df[['feature1', 'feature2', 'feature3']]
y = df['target']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# 3. Обучение модели
model = LogisticRegression()
model.fit(X_train, y_train)
score = model.score(X_test, y_test)
print(f'Model accuracy: {score:.4f}')
# 4. Сохранение результатов в БД
Session = sessionmaker(bind=engine)
session = Session()
predictions_df = pd.DataFrame({
'record_id': df.index,
'prediction': model.predict(X),
'probability': model.predict_proba(X)[:, 1]
})
predictions_df.to_sql('model_predictions', engine, if_exists='append', index=False)
session.close()
Преимущества SQLAlchemy
✓ Абстракция БД
- Один код работает с PostgreSQL, MySQL, SQLite
✓ Безопасность
- Защита от SQL injection через параметризованные запросы
✓ Удобство
- Работаешь с объектами Python, а не со строками SQL
✓ Производительность
- Connection pooling (переиспользование соединений)
- Lazy loading и eager loading
✓ Гибкость
- Можешь писать сырой SQL если нужно
- Или использовать высокоуровневый ORM
✓ Тестируемость
- Легко мокировать БД в тестах
Ограничения
✗ Кривая обучения
- Требует понимания как ORM так и SQL
✗ Производительность на сложных запросах
- Сгенерированный SQL может быть неоптимален
✗ Сложность отладки
- Трудно отследить какой SQL генерируется
Отладка SQL
from sqlalchemy import event, pool
import logging
# Включаем логирование SQL
logging.basicConfig()
logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)
engine = create_engine('postgresql://...', echo=True) # Выведет все SQL
# Или смотрим сгенерированный SQL
query = session.query(User).filter(User.age > 25)
print(query) # Выводит SQL statement
print(str(query.statement.compile(compile_kwargs={"literal_binds": True})))
Сравнение: SQL vs SQLAlchemy
# ══════════════════════════════════════════════════════════
# SQL (сырой SQL)
# ══════════════════════════════════════════════════════════
import sqlite3
conn = sqlite3.connect('db.sqlite')
cursor = conn.cursor()
cursor.execute(
'SELECT * FROM users WHERE age > ? ORDER BY username',
(25,)
)
results = cursor.fetchall()
conn.close()
# ══════════════════════════════════════════════════════════
# SQLAlchemy (ORM)
# ══════════════════════════════════════════════════════════
engine = create_engine('sqlite:///db.sqlite')
Session = sessionmaker(bind=engine)
session = Session()
results = session.query(User).filter(User.age > 25).order_by(User.username).all()
session.close()
# ══════════════════════════════════════════════════════════
# Преимущества SQLAlchemy:
# 1. Читаемость (объектно-ориентированный подход)
# 2. Безопасность (параметризованные запросы автоматически)
# 3. Переносимость (работает с разными СУБД)
# 4. Удобство (не нужно парсить кортежи)
# ══════════════════════════════════════════════════════════
Когда использовать SQLAlchemy
✓ ИСПОЛЬЗУЙ:
- Создание приложений с БД
- Frequent read/write операции
- Когда нужна абстракция от конкретной СУБД
- Complex business logic с данными
✗ НЕ используй (используй сырой SQL):
- One-off запросы для анализа
- Очень сложные SQL запросы
- Когда производительность критична
- Быстрый прототип (просто используй Pandas)
Для Data Scientist: рекомендуемый подход
# 1. Для изучения данных → используй Pandas
df = pd.read_sql('SELECT * FROM table LIMIT 100', engine)
# 2. Для production pipeline → используй SQLAlchemy ORM
from sqlalchemy.orm import Session
with Session(engine) as session:
results = session.query(Model).filter(...).all()
# 3. Для сложных аналитических запросов → сырой SQL через Pandas
df = pd.read_sql('SELECT ... FROM ... WHERE ...', engine)
# 4. Для сохранения результатов → ORM или to_sql
results_df.to_sql('results_table', engine, if_exists='append')
Заключение
SQLAlchemy — это:
- Essential инструмент для work с БД в Python
- Мощный ORM для абстракции таблиц
- Flexible toolkit для SQL queries
- Essential для production ML систем
Для Data Scientist: изучите основы SQLAlchemy для работы с production системами, но используйте Pandas для быстрого анализа данных.