python の mimetypes モジュールで若干ハマる

今回も技術話。python です。

Amazon Simple Storage Service (Amazon S3) を使って mysqldump ファイルを Amazon S3 にコピーしようかな、と思い、ZFS のスナップショットを Amazon S3 に保存する方法 (Python で途中まで) – 傀儡師の館.Python – 楽天ブログ(Blog) のスクリプトを参考に python でやってみようと思ったところ、mimetypes の動きに癖があることが分かったので、そのメモです(一文が長いなぁ)。

mysqldump-YYYYMMDD.sql.gz という SQL ファイルを gzip したファイルがあったとします。これを S3 にコピーします。S3 には content-type を指定しないといかんようで、参考にしたスクリプトでは mimetypes モジュールを使って特定しています。しかし、この mysqldump-YYYYMMDD.sql.gz だと None が帰ってきて mimetype が分かりません。

当初確認していたのは Debian ですが、この記事書くときに起動していたのは Gentoo だったので Gentoo の Python 環境で試してみます(起動する手間を惜しみました)。

$ file mysqldump-YYYYMMDD.sql.gz
mysqldump-YYYYMMDD.sql.gz: gzip compressed data, was “mysqldump-YYYYMMDD.sql”, from Unix, last modified: Sun Jun 27 21:05:59 2009

file コマンドで見ると gzip ファイルと判別します。これを python で確認してみます。

>>> import mimetypes
>>> mimetypes.guess_type(‘mysqldump-YYYYMMDD.sql.gz’)
(None, ‘gzip’)

mimetype は ‘None’ で不明。拡張子は gz なので gzip と判定しました。None だと S3 にアップできないので困りますね。

mimetypes モジュールはシステムのどこかから mimetype を判別しており、そこに書かれていない mimetype は None を返すのではないか、と思い mimetypes.py を覗いてみます。すると knownfiles というリストがありました。

knownfiles = [
“/etc/mime.types”,
“/etc/apache/conf/mime.types”, # Gentoo Apache 1
“/etc/apache2/conf/mime.types”, # Gentoo Apache 2
“/etc/httpd/mime.types”, # Mac OS X
“/etc/httpd/conf/mime.types”, # Apache
“/etc/apache/mime.types”, # Apache 1
“/etc/apache2/mime.types”, # Apache 2
“/usr/local/etc/httpd/conf/mime.types”,
“/usr/local/lib/netscape/mime.types”,
“/usr/local/etc/httpd/conf/mime.types”, # Apache 1.2
“/usr/local/etc/mime.types”, # Apache 1.3
]

ここに書かれた mime.types から探しているようですね。当方の Gentoo にあった mime.types は /etc/mime.types のみ。sql が書かれていないか grep してみます。

$ grep sql /etc/mime.types
$

書かれていませんでした。

次に gz で grep。

$ grep gz /etc/mime.types
# Note: Compression schemes like “gzip”, “bzip”, and “compress” are not
application/x-gtar gtar tgz taz
application/x-wingz wz
image/svg+xml svg svgz

tgz はあるけど gz はありません。mysqldump-YYYYMMDD.sql.gz は単一のテキストファイルなので、tar で固める必要がありません。tgz なら None で返ってこないで幸せになれたのに。

嘆いても進まないので、解決します。/etc/mime.types または ~/.mime.types に

text/x-sql sql

を追加すればよかったのですが、対応したときは別解にしました。時間も迫っていたので先に閃いたのが、ファイル名に ‘.txt’ を加えるというものでした。テキストファイルだからいいよね、という妥協です。すなわち “mysqldump-YYYYMMDD.sql.txt.gz” としたわけです。’.gz’ が拡張子じゃないか、という意見もあるかと思いますが、mimetypes.guess_type() は gz は一応展開している模様です。”mysqldump-YYYYMMDD.sql.txt” で評価しているということですね。

実際に python でいじってみましょう。

>>> import mimetypes
>>> mimetypes.guess_type(‘mysqldump-YYYYMMDD.sql.txt.gz’)
(‘text/plain’, ‘gzip’)
>>>

‘text/plain’ が帰ってきました。

ということでちょっと癖のある python モジュール mimetypes でした。

Comments are closed.