はじめに
Python の標準ライブラリの mimetypes モジュール を使って、
MIME Type を取得しようとしたら少しだけハマったのでメモを残す。
公式ドキュメント にもしっかり書いてあるが、
「ファイル名拡張子に関連付けられた MIME 型とを変換します」 となっている。
どうやらファイル名に含まれる拡張子しか見てくれていないっぽい。
今回は拡張子は無しの状態でファイルを判定したかったので、
mimetypes モジュールではダメだったというお話です。
mimetypes モジュール で試してみた
対象のファイルは png 画像
import mimetypes
IMAGE_FILE_PATH = './image.png'
print('===== .png =====')
print(f'-- mimetypes: {mimetypes.guess_type(IMAGE_FILE_PATH)[0]}')
$ python main.py
===== .png =====
-- mimetypes: image/png
ちゃんと取れてます。
拡張子無しで試す
import mimetypes
import shutil
IMAGE_FILE_PATH = './image.png'
print('===== 拡張子無し =====')
tmp = './dummy_image'
shutil.copy(IMAGE_FILE_PATH, tmp)
print(f'-- mimetypes: {mimetypes.guess_type(tmp)[0]}')
$ python main.py
===== 拡張子無し =====
-- mimetypes: None
None になってしまった。
.mp4 に偽装して試してみる
import mimetypes
import shutil
IMAGE_FILE_PATH = './image.png'
print('===== 拡張子を .mp4 の偽装 =====')
tmp = './dummy_image.mp4'
shutil.copy(IMAGE_FILE_PATH, tmp)
print(f'-- mimetypes: {mimetypes.guess_type(tmp)[0]}')
$ python main.py
===== 拡張子を .mp4 の偽装 =====
-- mimetypes: video/mp4
video/mp4
と判断されてしまった。
代わりに python-magic モジュールを使用
python-magic は libmagic
を使ってファイル種別を判定してくれる。
また libmagic
を使用するため、実行環境に libmagic
がインストールされている必要がある
インストールされていない場合は以下のように実行時にエラーが出てしまいます。
ImportError: failed to find libmagic. Check your installation
libmagic をインストール
自分は Mac を使用しているため、Homebrew でインストールしました。
$ brew install libmagic
python-magic をインストール
まずは python-magic モジュールをインストール
$ pip install python-magic
python-magic モジュールで試してみた
試し方は前述の mimetypes モジュールと同じです。
- png 画像
- 上記をコピーした拡張子無しファイル
- 同様に拡張子を .mp4 にしたファイル
png 画像
import magic
IMAGE_FILE_PATH = './image.png'
print('===== .png =====')
print(f'-- python-magic: {magic.from_file(IMAGE_FILE_PATH, mime=True)}')
$ python main.py
===== .png =====
-- python-magic: image/png
普通に取得できます。
拡張子無し
import shutil
import magic
IMAGE_FILE_PATH = './image.png'
print('===== 拡張子無し =====')
tmp = './dummy_image'
shutil.copy(IMAGE_FILE_PATH, tmp)
print(f'-- python-magic: {magic.from_file(tmp, mime=True)}')
$ python main.py
===== 拡張子無し =====
-- python-magic: image/png
mimetypes では None だったのに対し、ちゃんと取得できています。
.mp4 に偽装
import shutil
import magic
IMAGE_FILE_PATH = './image.png'
print('===== 拡張子を .mp4 の偽装 =====')
tmp = './dummy_image.mp4'
shutil.copy(IMAGE_FILE_PATH, tmp)
print(f'-- python-magic: {magic.from_file(tmp, mime=True)}')
$ python main.py
===== 拡張子を .mp4 の偽装 =====
-- python-magic: image/png
mimetypes では video/mp4
だったのに対し、ちゃんと取得できています。
まとめ
ファイル種別判定には mimetypes より python-magic を使ったほうが良い!
import mimetypes
import shutil
import magic
IMAGE_FILE_PATH = './image.png'
print('===== .png =====')
print(f'-- mimetypes: {mimetypes.guess_type(IMAGE_FILE_PATH)[0]}')
print(f'-- python-magic: {magic.from_file(IMAGE_FILE_PATH, mime=True)}')
print('')
print('===== 拡張子無し =====')
tmp = './dummy_image'
shutil.copy(IMAGE_FILE_PATH, tmp)
print(f'-- mimetypes: {mimetypes.guess_type(tmp)[0]}')
print(f'-- python-magic: {magic.from_file(tmp, mime=True)}')
print('')
print('===== 拡張子を .mp4 の偽装 =====')
tmp = './dummy_image.mp4'
shutil.copy(IMAGE_FILE_PATH, tmp)
print(f'-- mimetypes: {mimetypes.guess_type(tmp)[0]}')
print(f'-- python-magic: {magic.from_file(tmp, mime=True)}')
$ python main.py
===== .png =====
-- mimetypes: image/png
-- python-magic: image/png
===== 拡張子無し =====
-- mimetypes: None
-- python-magic: image/png
===== 拡張子を .mp4 の偽装 =====
-- mimetypes: video/mp4
-- python-magic: image/png