Как определить формат файла с помощью Python?

Поговорим на тему определения формата файла на основе содержания. В статье — обзор различных вариантов. Представлены специализированные библиотеки и пример вызова стандартной утилиты Unix для работы с типами файлов из Python.

Библиотека python-magic для различных форматов файлов

Если вам необходимо работать с различными форматами файлов, можно обратиться к python-magic. Эта библиотека через ctypes делает возможным доступ к libmagic — системной библиотеке. python-magic использует локальную базу данных магических чисел и поддерживает вывод как в описательном виде, так и в виде MIME-типа:

>>> import magic

>>> magic.from_file('iceland.jpg')
'JPEG image data, JFIF standard 1.01'

>>> magic.from_file('iceland.jpg', mime=True)
'image/jpeg'

>>> magic.from_file('greenland.png')
'PNG image data, 600 x 1000, 8-bit colormap, non-interlaced'

>>> magic.from_file('greenland.png', mime=True)
'image/png'

Библиотека imghdr для изображений

Существуют также библиотеки для более специализированных типов файлов. Например, стандартная библиотека Python имеет модуль imghdr, который делает то же самое только для типов файлов изображений:

>>> import imghdr
>>> imghdr.what('bass.gif')
'gif'

Библиотека fleep

Можно обратить внимание на библиотеку fleep. Библиотека имеют встроенную поддержку популярных форматов файлов.

import fleep

with open("png_image", "rb") as file:
    info = fleep.get(file.read(128))

print(info.type)  # prints ['image']
print(info.extension)  # prints ['png']
print(info.mime)  # prints ['image/png']

print(info.type_matches("image"))  # prints True
print(info.extension_matches("gif"))  # prints False
print(info.mime_matches("image/png"))  # prints True

Утилита file в Unix-подобных системах

В Unix-подобных системах команда file классифицирует каждый переданный аргумент на основе набора тестов. Существует три набора тестов: тесты файловой системы, тесты магических чисел и языковые тесты. Первый успешно пройденный тест печатает тип файла. Используя subprocess и shlex из Python можно получить результат:

import subprocess
import shlex

filename = 'your_file'
cmd = shlex.split('file --mime-type {0}'.format(filename))
result = subprocess.check_output(cmd)
mime_type = result.split()[-1]
print(mime_type)

Что же выбрать?

Наиболее общая рекомендация — использовать python-magic. Библиотека имеет хорошую репутацию и значительную распространенность. Однако в некоторых специфических случаях могут пригодиться другие рассмотренные решения.