zipfile でのファイル名の扱いもまともになってしまったっぽい

CJKV日中韓越情報処理

従来のzipfile.ZipFile.writeは、zipに格納されるファイル名に8ビット文字列をそのまま使っていたため、エンコーディングを自分で選ぶことができました。
(とゆーか、ライブラリ側が関知するところではなかった(^^;))
しかし、Python3.0からはUNICODE文字列で与える形式となり、かつ今のところエンコーディングを変更することはできないみたい。

UNICODE文字列に起因する問題

まともになったと思ったら他の仕様無視なアーカイバ*1で作られたアーカイブを扱えなくなったという罠。
LHAとZIP―圧縮アルゴリズム×プログラミング入門

appnote [pkware.com]のAPPENDIX D - Language Encoding (EFS)に従っただけですね。

Re:UNICODE文字列に起因する問題

とコメントされてますが、ZIP の仕様にこの変更が入ったのは

6.3.0         -Added tape positioning storage          09/29/2006
parameters
(中略)
-Added option for Unicode filename
storage

http://www.pkware.com/documents/casestudies/APPNOTE.TXT

と最近の話。それ以前は

APPENDIX D - Language Encoding (EFS)

                                                                      • -

The ZIP format has historically supported only the original IBM PC character
encoding set, commonly referred to as IBM Code Page 437.

http://www.pkware.com/documents/casestudies/APPNOTE.TXT

てなわけで(Pythonでいう)cp437のみという建前*2

問題は Unicode でファイル名が入っている場合ではなくて、Unicode フラグが立っていない場合の扱いが Python 3.0 でまともになってしまったせいでこの cp437 というエンコードをちゃんと扱ってしまい(今までは事後にローカルなエンコーディングで処理していたりしたのが事前に)cp437でデコードされてしまうようになってしまった、という点の方。元々仕様外の使い方をしていたのが悪いといえばその通りなのですが……。

まあ ZIP アーカイブを作るときにちゃんと Unicode 対応しているアーカイバ*3を使えばいいだけの話*4ではあるのですが。

Unicode 文字列自体もそうだけれども、Python の場合 Python が正しい扱いをしているせいで他の間違った扱いをしているプログラム/環境との不整合を起こしてしまい、そのせいでまるで Python が間違っているかのように言われてしまう事が多い感じ。

*1:Windows標準機能の「圧縮 (zip 形式) フォルダ.zip」とかも()

*2:例によってこれを無視してローカルなエンコードでのバイト列のままほうりこまれて使われたので、違うエンコードでのファイル名の環境に持ってゆくと文字化けしまくっていたわけですが

*3:Explzh - 多形式に対応した、圧縮解凍ソフト とか

*4:あるいは、それこそ Python 3.0 でアーカイブするとか