Урок 80. MySQL и Python
⚡ Кратко: суть темы
MySQL и Python — подключаемся к реляционной базе данных из Python через библиотеку PyMySQL, выполняем SQL-запросы и безопасно обрабатываем результаты.
- Устанавливаем
pip install pymysqlи открываем соединение черезpymysql.connect(...). - Через объект
cursorвыполняем запросы методомexecute(), а результаты читаем черезfetchone(),fetchmany(),fetchall()или циклfor row in cursor. - Параметры запроса всегда передаём отдельно от текста SQL — через
%sили%(name)s— чтобы избежать SQL-инъекций. - Для надёжности используем
with connection.cursor() as cursorи обрабатываем ошибки черезtry ... except pymysql.MySQLError.
Что запомнить: никогда не подставляй пользовательский ввод напрямую в строку SQL — только параметризованные запросы.
Частая ошибка: забыть запятую в кортеже из одного значения: (value,) обязательна.
📖 Зачем нужны базы данных
Когда программы растут, данные нужно хранить вне кода: о товарах, пользователях, заказах, сообщениях и т.д. Базы данных позволяют:
- хранить структурированные данные вне программы;
- быстро искать, обновлять и удалять записи;
- работать с большими объёмами без загрузки всего в память;
- обеспечить многопользовательский доступ и защиту данных;
- делать программы надёжнее и масштабируемее.
MySQL — одна из самых популярных реляционных СУБД. В этом уроке мы научимся подключаться к ней из Python, выполнять запросы, получать результаты и защищать код от типичных ошибок.
🔌 Библиотеки для работы с MySQL
| Библиотека | Особенности |
|---|---|
PyMySQL | Простая, полностью на Python, работает стабильно на всех ОС |
mysql-connector-python | Официальная библиотека от MySQL |
MySQLdb / mysqlclient | Очень быстрая, но сложнее в установке (особенно на Windows) |
Мы будем использовать PyMySQL:
pip install pymysql
🔑 Подключение к базе данных
Чтобы подключиться, импортируем модуль и вызываем pymysql.connect() с параметрами подключения:
import pymysql
connection = pymysql.connect(
host="localhost", # адрес сервера базы данных
user="root", # имя пользователя
password="yourpassword", # пароль
database="yourdatabase", # название базы данных (необязательно)
charset="utf8mb4", # кодировка соединения (рекомендуется для кириллицы)
)
Параметры можно хранить в словаре и распаковывать через ** — это удобно, если подключений несколько или конфигурация читается из файла:
import pymysql
config = {
"host": "ich-db.edu.itcareerhub.de",
"user": "ich1",
"password": "password",
"database": "hr",
}
connection = pymysql.connect(**config)
После создания соединения можно проверить его состояние:
if connection.open:
print("Connection successful!")
Открытые соединения занимают ресурсы сервера, поэтому соединение нужно закрывать:
connection.close()
🖱️ Курсор: выполнение запросов
Курсор — это объект, через который отправляются SQL-запросы и получаются результаты.
cursor = connection.cursor()
cursor.execute("SELECT * FROM departments")
cursor.execute(sql)отправляет SQL-запрос к базе данных.- SQL-запрос передаётся строкой.
- Можно выполнять любые запросы:
SELECT,INSERT,UPDATE,DELETEи др. - После каждого нового запроса старые результаты очищаются.
- При ошибке в запросе выбрасывается исключение.
После использования курсор закрывают вручную:
cursor.close()
📥 Получение результатов
После SELECT данные остаются в курсоре. Для чтения используются методы:
| Метод | Что делает |
|---|---|
fetchone() | Возвращает одну следующую строку или None |
fetchmany(size) | Возвращает заданное число строк |
fetchall() | Возвращает все оставшиеся строки |
for row in cursor | Итерируется по строкам как по итератору |
Курсор сдвигается после каждого чтения: повторный вызов fetchall() вернёт пустую коллекцию, если строки уже были считаны.
🛡️ Параметризованные запросы
Никогда нельзя подставлять значения пользователя напрямую в строку SQL — это приводит к SQL-инъекциям. Вместо этого используют плейсхолдеры %s и передают значения отдельно:
cursor.execute(
"SELECT * FROM employees WHERE department_id = %s OR salary > %s",
(60, 20000)
)
for row in cursor:
print(row)
Если значение одно, кортеж всё равно нужен — не забудьте запятую:
cursor.execute(
"SELECT * FROM employees WHERE department_id = %s",
(100,) # обязательно запятая!
)
Именованные параметры
Для большей читаемости можно использовать именованные плейсхолдеры %(name)s и словарь:
cursor.execute(
"SELECT * FROM employees WHERE department_id = %(dep_id)s OR salary > %(min_salary)s",
{"min_salary": 20000, "dep_id": 60}
)
for row in cursor:
print(row)
⚠️ Обработка ошибок
При работе с базой могут возникать ошибки подключения, неверный SQL, отсутствие таблицы и т.д. Чтобы программа не падала, используем try ... except:
import pymysql
try:
connection = pymysql.connect(
host="ich-db.edu.itcareerhub.de",
user="root",
password="wrong_password",
database="test"
)
print("Connected!")
except pymysql.MySQLError as e:
print("Connection error:", e)
Базовый класс всех исключений PyMySQL — pymysql.MySQLError. Часто используются также pymysql.ProgrammingError (ошибки SQL) и pymysql.OperationalError (проблемы соединения).
🧰 Контекстный менеджер with
Конструкция with автоматически закрывает соединение и курсор, даже если внутри блока произошла ошибка:
with pymysql.connect(
host="ich-db.edu.itcareerhub.de",
user="ich1",
password="password",
database="hr"
) as connection:
with connection.cursor() as cursor:
cursor.execute("SELECT * FROM employees")
for row in cursor:
print(row)
✨ Современные практики
python-dotenv и ORM (например, SQLAlchemy).
- Храните пароли и логины в переменных окружения, а не в коде.
- Для локальной разработки удобна библиотека
python-dotenv: положите секреты в файл.envи загрузите черезload_dotenv(). - Никогда не собирайте SQL через f-string или конкатенацию строк с пользовательским вводом.
- Используйте
withдля автоматического закрытия ресурсов. - Именуйте конфигурационные словари в
UPPER_CASE, если они константы (PEP 8).