Базы данных в Python: драйверы, SQL и ORM
Основные подходы к работе с базами данных в Python
Как унифицировать работу с разными СУБД и упростить разработку?
SQLAlchemy - наиболее эффективное решение для сложных проектов
SQLAlchemy предоставляет два уровня работы: Core (низкоуровневый SQL-конструктор) и ORM (объектно-реляционное отображение). Это позволяет писать код, независимый от конкретной базы данных, и сочетать гибкость SQL с удобством работы с объектами Python.
from sqlalchemy import create_engine, text
engine = create_engine('sqlite:///example.db')
with engine.connect() as conn:
result = conn.execute(text("SELECT 'Привет, мир'"))
print(result.fetchone()[0])
базы данных в python (базы данных в python)
Привет, мир
Пояснение: create_engine создаёт точку подключения. Строка подключения 'sqlite:///example.db' указывает на файл SQLite. Для PostgreSQL строка будет 'postgresql://user:pass@localhost/db'. Метод connect() возвращает контекстный менеджер, обеспечивающий автоматическое закрытие соединения.
Типичные проблемы:
- Ошибка импорта: если не установлен пакет
sqlalchemy- используйтеpip install sqlalchemy. - Неверная строка подключения: синтаксис может различаться. Например, для MySQL требуется
'mysql+pymysql://...'. - Конфликты сессий: при использовании ORM следует правильно настроить
SessionLocalи применять паттерн единой сессии на запрос.
Как выполнять простые операции без ORM?
Вариант 1: Встроенный модуль sqlite3
Подходит для локальных приложений, прототипов и тестов. Не требует установки дополнительных пакетов.
import sqlite3
conn = sqlite3.connect(':memory:')
cursor = conn.cursor()
cursor.execute('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)')
cursor.execute('INSERT INTO users VALUES (?, ?)', (1, 'Анна'))
conn.commit()
print(cursor.lastrowid)
1
Пояснение: sqlite3.connect(':memory:') создаёт базу в оперативной памяти. Плейсхолдеры ? защищают от SQL-инъекций. После изменения данных обязателен commit().
Ошибки:
- Забытый commit - данные не сохраняются.
- Закрытие соединения без commit - изменения теряются.
- Неоднократное открытие одного файла - возможны блокировки.
Как подключиться к PostgreSQL из Python?
Вариант 2: Драйвер psycopg2
Рекомендуется для продакшен-систем на PostgreSQL. Устанавливается через pip install psycopg2-binary.
import psycopg2
conn = psycopg2.connect(
host='localhost',
port=5432,
dbname='testdb',
user='postgres',
password='secret'
)
cur = conn.cursor()
cur.execute('SELECT version()')
print(cur.fetchone())
('PostgreSQL 15.4 (Debian 15.4-1.pgdg120+1) on x86_64-pc-linux-gnu',)
Пояснение: psycopg2.connect принимает параметры подключения. После работы нужно закрыть курсор и соединение, либо использовать контекстный менеджер.
Проблемы:
- Неверный пароль/хост -
OperationalError: could not connect to server. - Отсутствие библиотеки libpq - при установке
psycopg2(не binary) требуется компиляция. Используйтеpsycopg2-binaryдля простоты. - Утечка соединений - всегда закрывайте соединение, лучше через
with conn:.
Как работать с MySQL?
Вариант 3: Драйвер mysql-connector-python
Официальный коннектор от Oracle. Установка: pip install mysql-connector-python.
import mysql.connector
conn = mysql.connector.connect(
host='127.0.0.1',
user='root',
password='pass',
database='mydb'
)
cursor = conn.cursor()
cursor.execute('SELECT NOW()')
print(cursor.fetchone())
(datetime.datetime(2025, 3, 21, 14, 55, 30),)
Пояснение: строка подключения может быть передана как словарь. Для безопасной передачи пароля используйте переменные окружения.
Частые ошибки:
- Authentication plugin 'caching_sha2_password' - добавьте
auth_plugin='mysql_native_password'. - Не найден database - проверьте имя базы.
- Закрытие соединения - используйте
conn.close()или менеджер контекста.
# Пример 1. SQLAlchemy ORM: связи между таблицами и транзакции
from sqlalchemy import create_engine, Column, Integer, String, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship
engine = create_engine('sqlite:///university.db', echo=True)
Base = declarative_base()
class Student(Base):
__tablename__ = 'students'
id = Column(Integer, primary_key=True)
name = Column(String(50))
group_id = Column(Integer, ForeignKey('groups.id'))
group = relationship('Group', back_populates='students')
class Group(Base):
__tablename__ = 'groups'
id = Column(Integer, primary_key=True)
name = Column(String(30))
students = relationship('Student', back_populates='group')
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
# Добавление объектов в транзакции
group = Group(name='CS-101')
student = Student(name='Иван Петров', group=group)
session.add(group)
session.add(student)
session.commit()
# Запрос с join
result = session.query(Student).join(Group).filter(Group.name == 'CS-101').all()
for s in result:
print(f"Студент {s.name} из группы {s.group.name}")
session.close()
Студент Иван Петров из группы CS-101
# Пример 2. psycopg2: использование пула соединений
from psycopg2 import pool
connection_pool = pool.SimpleConnectionPool(
2, 10, # min, max connections
host='localhost',
dbname='postgres',
user='postgres',
password='pass'
)
conn = connection_pool.getconn()
try:
cur = conn.cursor()
cur.execute('SELECT count(*) FROM pg_stat_activity')
print('Активные соединения:', cur.fetchone()[0])
finally:
connection_pool.putconn(conn)
# Закрытие пула при завершении приложения
# connection_pool.closeall()
Активные соединения: 3
# Пример 3. sqlite3: работа со встроенными функциями
import sqlite3
conn = sqlite3.connect(':memory:')
conn.execute('CREATE TABLE items (id, price)')
conn.execute('INSERT INTO items VALUES (1, 250)')
conn.execute('INSERT INTO items VALUES (2, 450)')
# Создание пользовательской функции
conn.create_function('format_price', 1, lambda x: f"{x:.2f} руб")
cur = conn.execute('SELECT format_price(price) FROM items')
for row in cur:
print(row[0])
250.00 руб 450.00 руб