Help us understand the problem. What is going on with this article?

Python で MIME Type を取得する

はじめに

Python の標準ライブラリの mimetypes モジュール を使って、
MIME Type を取得しようとしたら少しだけハマったのでメモを残す。

公式ドキュメント にもしっかり書いてあるが、
「ファイル名拡張子に関連付けられた MIME 型とを変換します」 となっている。
どうやらファイル名に含まれる拡張子しか見てくれていないっぽい。

今回は拡張子は無しの状態でファイルを判定したかったので、
mimetypes モジュールではダメだったというお話です。

mimetypes モジュール で試してみた

対象のファイルは png 画像

main.py
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

ちゃんと取れてます。

拡張子無しで試す

main.py
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 に偽装して試してみる

main.py
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-magiclibmagic を使ってファイル種別を判定してくれる。
また libmagic を使用するため、実行環境に libmagic がインストールされている必要がある

インストールされていない場合は以下のように実行時にエラーが出てしまいます。

libmagicがインストールされていない環境でpython-magicを使った時のエラー
ImportError: failed to find libmagic.  Check your installation

libmagic をインストール

自分は Mac を使用しているため、Homebrew でインストールしました。

libmagicをインストール
$ brew install libmagic

python-magic をインストール

まずは python-magic モジュールをインストール

$ pip install python-magic

python-magic モジュールで試してみた

試し方は前述の mimetypes モジュールと同じです。

  • png 画像
  • 上記をコピーした拡張子無しファイル
  • 同様に拡張子を .mp4 にしたファイル

png 画像

main.py
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

普通に取得できます。

拡張子無し

main.py
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 に偽装

main.py
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 を使ったほうが良い!

main.py
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
Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away