python-magic: самый практичный способ доверять содержимому файла, а не расширению
Когда на сервере появляется функция загрузки изображений, рано или поздно возникают такие требования.
- «Файл пришёл как
.png, но действительно ли это PNG?» - «Нужно сначала определить, является ли файл изображением или документом.»
- «Перед тем как вызвать внешние парсеры (Pillow/OpenCV), хотелось бы хотя бы проверить тип.»
В этом случае самым надёжным отправным пунктом является содержимое файла, а не его расширение. И самый простой способ получить «содержимое‑базированную» проверку – это python-magic.
Что делает python-magic
python-magic – это обёртка над C‑библиотекой libmagic. Libmagic анализирует заголовок (первые несколько байт) файла и определяет его тип. Такая же функциональность доступна в Unix‑команде file.
Итак:
file(команда Linux) = «интерфейс в терминале»libmagic= «ядро‑движок (логика определения)»python-magic= «тонкая обёртка, позволяющая вызывать libmagic из Python»
В этой статье мы сосредоточимся на python-magic и разберём, как именно этот движок определяет тип файла.
Как работает ядро libmagic

Суть libmagic проста:
«Читает базу правил определения типа файла, проверяет байты файла согласно этим правилам и выводит наиболее вероятный результат.»
База правил – это magic database (magic pattern DB), которая обычно поставляется в скомпилированном виде (magic.mgc).
1) «Magic file» – набор правил
Правила состоят из:
- Где смотреть (offset – позиция в файле)
- Как читать (type – байт/строка/целое и т.д.)
- С чем сравнивать (expected value/pattern)
- Какой вывод (message/MIME и т.п.)
Каждое правило проверяется строка за строкой, и при совпадении переходит к более конкретным подправилам, образуя иерархию.
Для более подробного изучения команды file можно перейти по ссылке:
2) База правил – текст и скомпилированный формат
Magic DB может быть как читаемым текстом, так и скомпилированным бинарным файлом (.mgc) для повышения производительности.
3) Итог: проверка содержимого вместо расширения
file всегда использует содержимое, а не расширение, чтобы определить тип. python-magic просто переносит эту философию в одну строку Python‑кода.
Как использовать python-magic
Существует два основных паттерна использования.
1) Получить MIME‑тип (самый практичный)
Полезно при обработке загрузок, маршрутизации, логировании и метриках.
import magic
mime = magic.from_file("upload.bin", mime=True)
print(mime) # например: image/png
python-magic использует libmagic для определения типа файла, как и команда file.
2) Проверка по буферу (удобно для потоков загрузки)
Перед сохранением на диск часто хочется быстро проверить первые байты.
import magic
with open("upload.bin", "rb") as f:
head = f.read(4096)
mime = magic.from_buffer(head, mime=True)
print(mime)
Буферная проверка особенно полезна как «первый фильтр» до сохранения файла.
Где это полезно с точки зрения разработчика
1) Первая линия защиты при проверке загрузок
- Не полагаться только на расширение
- Минимально проверить, можно ли обрабатывать файл как изображение
2) Точки ветвления в пайплайне обработки
- Если изображение – перейти к ресайз/тумбне
- Если PDF/ZIP – отправить в другую очередь
- Если тип неизвестен – изолировать/отклонить/дополнительно проверить
3) Сокращение затрат до вызова «тяжёлых декодеров»
Pillow и подобные декодеры мощны, но их вызов увеличивает потребление памяти, CPU и поверхность уязвимостей. python-magic позволяет заранее решить, стоит ли вызывать декодер.
Важный практический момент: libmagic – это только предположение/идентификация. Для полной безопасности (запрет вредоносных нагрузок) нужны дополнительные проверки (белый список, ограничение размера, sandbox‑декодинг и т.д.).
Итог: python-magic – самый лёгкий способ получить определение типа файла в коде
python-magic не занимается обработкой изображений, а лишь быстро сообщает, как файл следует трактовать.
- Движок – libmagic, как в
file - Метод – «правила + проверка байтов»
- Практика – проверка загрузок, маршрутизация, экономия ресурсов
Освоив его, вы сможете в любой среде, где недоступны полноценные библиотеки, построить цепочку «определение → ветвление → защита».
Предвкушение следующей статьи
- Что гарантируют методы
open(),load(),verify()в Pillow (PIL) и когда их использовать? Мы разберём их работу и назначение.
Смотрите также