В сети до сих пор висят мануалы из 2013, где предлагают писать громоздкие скрипты на PHP с библиотекой PHPExcel или использовать встроенный импорт через веб-интерфейс phpMyAdmin. На практике эти методы спотыкаются на первой же тысяче строк: слетают кодировки, ломаются форматы дат, а дробные числа округляются до целых.
При взаимодействии разработки с менеджментом или бухгалтерией регулярно всплывает одна и та же задача. Нужно либо выгрузить таблицу из базы в Эксель для отчёта, либо, наоборот, залить обратно в СУБД тяжелый xlsx. файл со свежими ценами или списком контрагентов. Настраивать тяжелые ETL-системы ради разовой выгрузки неэффективно. Проблема решилась написанием короткого CLI-скрипта на Python - mysql_bridge. Утилита обеспечивает сквозную двустороннюю конвертацию данных, автоматически анализирует структуру и сохраняет исходные типы на лету. Исходный код скрипта и Readme Здесь. Если Вас заинтересовала или статья была полезна, поддержите звездочками.
Как устроен двусторонний мост
Вся логика инструмента умещается за счёт связки pandas, sqlalchemy и движка openpyxl. Скрипт работает с файлами Эксель напрямую на уровне бинарного кода, поэтому его можно запускать на серверах без установленного офисного софта. Утилита работает в двух режимах.
Экспорт. Из MySQL в Excel
Для выгрузки данных скрипт использует абстракцию SQLAlchemy, подключается к базе и одной командой считывает таблицу в виртуальный DataFrame, сохраняя системные типы данных СУБД.
def export_to_excel(table_name, excel_path):
engine = create_engine(DATABASE_URL)
df = pd.read_sql_table(table_name, con=engine)
df.to_excel(excel_path, index=False, engine=‘openpyxl’)
Импорт. Из Excel в MySQL с автосозданием таблиц
Самая частая проблема ручного импорта - необходимость предварительно создавать пустую таблицу в MySQL через CREATE TABLE.
В разработанном мною скрипте этот процесс автоматизирован. Pandas предварительно сканирует Эксель-файл, определяет типы данных в памяти (строки, целые числа, вещественные числа, даты) и самостоятельно генерирует валидную таблицу в MySQL перед заливкой строк.
Флаг if_exists='replace' гарантирует, что если старая техническая таблица уже существовала в базе, она будет корректно пересоздана под новую структуру файла.
def import_from_excel(excel_path, table_name):
engine = create_engine(DATABASE_URL)
df = pd.read_excel(excel_path, engine=‘openpyxl’)
df.to_sql(table_name, con=engine, index=False, if_exists=‘replace’)
Тестирование и запуск в консоли
MySQL -> Excel
Перед запуском скрипта необходимо установить зависимости, выполнив команду
pip install pandas openpyxl sqlalchemy pymysql. Инструмент управляется через флаги, позволяя экспортировать данные из MySQL в Excel (--mode export) или импортировать обратно (--mode import), с автоматической обработкой типов данных и блокировок файлов. Рассмотрим на моём примере.
-
Открываем терминал в VS Code и ставим необходимые библиотеки:
pip install pandas openpyxl sqlalchemy pymysql

После установки библиотек открываем код
bridge.pyи прописываем доступы к нашей бд в переменнуюDATABASE_URL. Тестирование проводилось на локальной базеmedoiy_magazin.-
Для проверки режима экспорта выгрузим существующую таблицу товаров
productsв файл Excel. Для этого в терминале запускается следующая команда с флагами:python bridge.py --mode export --table products --file products.xlsx



Excel -> MySQL
Для проверки обратного режима возьмем тестовый файл с новыми данными и зальем его в СУБД. Скрипт автоматически просканирует файл, определит типы колонок в памяти и сам создаст новую таблицу taste ,в нашей базе medoiy_magazin без предварительного написания SQL-запросов. Команда для импорта:
python bridge.py --mode import --file taste.xlsx --table taste.
Выгружаем таблицу Эксель в MySQL



Разработанный автономный инструмент оптимизирует обмен данными между СУБД и таблицами, предлагая CLI-решение для автоматизации отчетности и миграции без использования тяжелых ETL-систем. Утилита предназначена для регулярных выгрузок и интеграции в рабочие процессы, а код и документация открыты для комьюнити. Познакомьтесь с проектом на GitHub и поддержите его. Сюда
Akina
Моё личное мнение - много лишнего. Уже ж гарантированно есть два достаточно мощных инструмента - MySQL и Excel, которых более чем достаточно для решения задачи, так какой великий смысл наворачивать ещё кучу инструментов (pandas, sqlalchemy и openpyxl)? Особенно если их (а то ещё и python до кучи) в системе изначально не имеется. Хотя надо-то всего лишь в Excel (вручную либо VBA-процедурой) пересохранить файл в CSV, или загрузить данные из того же формата, а с конвертацией в обе стороны (и созданием таблицы при необходимости) прекрасно справится достаточно несложная хранимая процедура на MySQL.
laenij Автор
Спасибо за взгляд из двухтысячных. Ручные манипуляции с CSV ломают структуру данных на первом же текстовом поле, где внутри ячейки окажутся обычные запятые или кавычки. Заставлять Linux-сервер бд тратить процессорное время на парсинг внутри хранимых процедур - значит положить СУБД при росте нагрузок. В 2026 году выполнить pip install и развернуть окружение на Python - это секундная задача для любого бэкендера, библиотеки весят копейки, а утилита работает автономно в фоне по cron без необходимости держать открытым графический интерфейс Excel для работы макросов. инструмент создан для нормальной автоматизации, чтобы инженеры не заставляли менеджеров вручную возиться с форматами. Мне кажется странным, экономить 20мб на легковесных библиотеках
Akina
Ну это заведомо неверное утверждение. Будь так - CSV не был бы стандартным средством переноса информации. Все текстовые поля (а при необходимости - вообще все поля) оборачиваются в кавычки, а кавычки внутри значения удваиваются либо экранируются - и никаких проблем ни с запятыми, ни с кавычками.
Описанная вами процедура - одноразовая. Это не однотипные запросы, которые летят от кучи клиентов большим и непредсказуемым потоком. Посему опасности "положить сервер" просто нет. Вот если бы импортировался, не приведи господи, XML, тогда да - процедура парсинга и импорта в MySQL тяжёлая и крайне по памяти прожорливая (кто импортировал ФИАС - знает).
И учтите ещё один момент. Сервер БД специально приспособлен и оптимизирован для пакетной обработки данных, его собственно для этого и создавали. А уж по производительности и имеющимся ресурсам он вообще кроет клиента как бык овцу. К тому же передача одного CSV и передача набора записей - это несколько различающиеся нагрузки на сетевую подсистему.
PS. К слову - а как ваш скрипт поведёт себя, если передаваемые данные содержат минорные форматные погрешности?
laenij Автор
Вы правы насчет стандартов в CSV, но на практике менеджеры присылают файлы из Excel, где ломаются переносы строк внутри ячеек, слетают длинные id в непонятный вид вроде 1E+11 или каверкаются даты. Из-за этого плоский формат требует постоянной ручной доработки. Процедура импорта действительно может быть разовой, но перекладывание логики парсинга файлов на сторону СУБД нарушает главный принцип разработки - разделение обязанностей. База должна быстро хранить и отдавать данные, а обрабатывать файлы должно легковесное приложение на Python, не забивая процессор MySQL лишней работой.
Что касается мелких погрешностей в файле: под скриптом стоит библиотека pandas. Если в файле будут пропуски или мелкие косяки, скрипт не упадет, а просто автоматически заменит проблемные места на NaN и спокойно зальет таблицу дальше. Чтобы добиться такой же стабильности внутри хранимой процедуры на SQL, придется писать обработчик ошибок, который займет гораздо больше строчек, чем весь скрипт. В конце концов, это просто еще один готовый вариант автоматизации, который экономит время, и хуже от его наличия не будет.
Akina
Позволю себе не согласиться. Все три описанные проблемы - это явно проблемы на присылающей стороне. Причём если последние две - результат неправильно выбранного формата ячеек, то откуда взялась первая и что она есть, я вообще не понимаю, её просто не должно существовать. И вместо того, чтобы надавать менеджеру по шее за некачественную работу, вы предлагаете по-тихому исправить все допущенные им косяки, и пусть его халтурит дальше.
Это ещё зачем?
А вот это уже плохо. Получается, что скрипт по-тихому, никому не сообщая, сохраняет на сервере заведомо некорректные данные. ИМХО единственное правильное поведение в случае любой погрешности - это пропуск импорта проблемной записи с занесением её исходных данных в соотв. лог. Совсем хорошо - копирование "сырых" данных в специально предназначенную для этого таблицу. А если данные имеют внутренние ссылки, то процесс вообще должен быть остановлен до устранения выявленных проблем в исходных данных.
laenij Автор
Вы абсолютно правы, данные нельзя молча искажать в продакшене, но никакого сознательного умалчивания ошибок в коде нет: замена на NaN - это стандартное базовое поведение библиотеки Pandas при встрече с пустыми ячейками или некорректными форматами, и любой разработчик, использующий этот стек, знаком с такой логикой. Скрипт закрывает стандартную часть автоматизации рутины, и на практике никаких сбоев с типами данных при его работе не возникало. При этом никто не говорит, что автоматизация должна быть слепой панацеей, на которую нужно исключительно опираться - в любом случае финальные данные всегда можно подправить . Но наличие двух подходов в арсенале всегда лучше, чем один. Что касается идеи "надавать менеджеру по шее за халтуру" - всегда существует банальный человеческий фактор, кто-то где-то мог просто не доглядеть в файле, и это нормальный рабочий процесс. Я только учусь, развиваюсь в бэкенде, код открыт, поэтому любые подобные шероховатости с типами или логированием легко дорабатываются и исправляются в следующих коммитах. Это просто локальный, легковесный скрипт для отработки навыков и быстрой подстраховки