◾️はじめに
https://dk521123.hatenablog.com/entry/2025/12/19/233012
で合成データを考えた際に、 そのファイルの元になったファイル形式 (当面では、CSV/DSV(Delimiter Separated Values), Parquet) が分からないと、実装難しいかなっと思った。 そこで、今回は、Pythonでファイル形式判定を考える。
目次
【0】ファイル形式判定ライブラリ 【1】python-magic 1)使用上の注意 2)インストール 3)サンプル 【2】filetype 1)使用上の注意 2)インストール 3)サンプル 【3】mimetypes 1)使用上の注意 2)サンプル 【4】ファイル形式判定を自作で考える 例1:CSV/DSV, Parquetの判定
【0】ファイル形式判定ライブラリ
| ライブラリ名 | 精度・対応数 | 導入のしやすさ | 判定方法 |
|---|---|---|---|
| python-magic | ★★★ | ★★☆ | マジックナンバー |
| filetype | ★★☆ | ★★★ | マジックナンバー |
| mimetypes | ★☆☆ | ★★★ (標準) | 拡張子 |
【1】python-magic
* Unix系のfileコマンドで使用されているlibmagicというライブラリのラッパー
https://pypi.org/project/python-magic/
1)使用上の注意
* Linuxコマンドのラッパーのため、OS依存する => Windowsなどの環境では、別途libmagicのインストールが必要になる場合がある
2)インストール
MACの場合
brew install libmagic pip install python-magic
3)サンプル
import magic # ファイルパスから判定 file_type = magic.from_file("sample.csv") print(file_type) # CSV ASCII text # MIMEタイプ(image/jpegなど)で取得したい場合 mime = magic.Magic(mime=True) print(mime.from_file("sample.csv")) # text/csv print("-----") # ファイルパスから判定 file_type = magic.from_file("sample.dsv") print(file_type) # ASCII text, with CRLF line terminators # MIMEタイプ(image/jpegなど)で取得したい場合 mime = magic.Magic(mime=True) print(mime.from_file("sample.dsv")) # text/plain
参考文献
https://omomuki-tech.com/archives/2390
【2】filetype
* 外部ライブラリに依存せず、軽量・純Python製 * 動作が速く、インストールが簡単
1)使用上の注意
* サポートしているファイル形式が 主要なもの(画像、動画、音声、アーカイブなど)に限定 => CSV, JSONなどのテキストは判定できなかった
2)インストール
pip install filetype
3)サンプル
import filetype kind = filetype.guess('sample.pdf') if kind is None: print('判定できませんでした') else: print('拡張子:', kind.extension) # 拡張子: pdf print('MIMEタイプ:', kind.mime) # MIMEタイプ: application/pdf
【1】mimetypes
* Python標準ライブラリ
1)使用上の注意
* 主に拡張子から判定するため、ファイルの中身が壊れていたり、 拡張子が偽装されている場合は正しく判定できない
2)サンプル
import mimetypes mime_type, _ = mimetypes.guess_type('sample.pdf') print(mime_type) # 'application/pdf' mime_type, _ = mimetypes.guess_type('sample.csv') print(mime_type) # 'text/csv' mime_type, _ = mimetypes.guess_type('sample.dsv') print(mime_type) # 'None' mime_type, _ = mimetypes.guess_type('my_metadata.json') print(mime_type) # 'application/json' mime_type, _ = mimetypes.guess_type('compose.yml') print(mime_type) # 'None' mime_type, _ = mimetypes.guess_type('demo2.py') print(mime_type) # 'text/x-python' mime_type, _ = mimetypes.guess_type('sample.parquet') print(mime_type) # None
【4】ファイル形式判定を自作で考える
例1:CSV/DSV, Parquetの判定
判定のロジック
* Parquetはバイナリデータ、CSVはテキストデータという大きな違いがあるため、 以下のフローで判定。 + Parquetの判定: 先頭4バイトが PAR1 かどうかを確認する。 + CSV/テキストの判定: PAR1 でなければテキストとして読み込み、 csv.Sniffer で区切り文字を推測
サンプル
import csv def identify_file_format(file_path): with open(file_path, 'rb') as f: # 1. Parquetの判定 (先頭4バイトを確認) header = f.read(4) if header == b'PAR1': return {"format": "Parquet", "delimiter": None} # 2. CSV/DSVの判定 try: with open(file_path, 'r', encoding='utf-8') as f: sample = f.read(2048) # 先頭2KBをサンプルとして読み込む # csv.Snifferで区切り文字を推測 # delimiters引数に判定したい文字をリストアップできます sniffer = csv.Sniffer() dialect = sniffer.sniff(sample, delimiters=[',', '|', '\t', ';']) return { "format": "CSV/DSV", "delimiter": dialect.delimiter } except Exception as e: return {"format": "Unknown or Error", "details": str(e)} # テスト実行 result = identify_file_format("sample.csv") # 形式: CSV/DSV, 区切り文字: , print(f"形式: {result['format']}, 区切り文字: {result['delimiter']}") result = identify_file_format("sample.dsv") # 形式: CSV/DSV, 区切り文字: | print(f"形式: {result['format']}, 区切り文字: {result['delimiter']}") result = identify_file_format("sample.parquet") # 形式: Parquet, 区切り文字: None print(f"形式: {result['format']}, 区切り文字: {result['delimiter']}")
関連記事
AWS上に合成データ生成システムを構築する 〜 構想編 〜
https://dk521123.hatenablog.com/entry/2025/12/19/233012
Python 〜 Faker 〜
https://dk521123.hatenablog.com/entry/2025/12/20/001758
Python SDV 〜 入門編 〜
https://dk521123.hatenablog.com/entry/2025/12/21/000330
Pandas ~ Parquet ~
https://dk521123.hatenablog.com/entry/2024/09/06/004125