ID3タグ@Python

上の日記忘れに関連して3月末の日記もちょろっと見たのだが、そこで解決していなかった問題を発見。id:tomoemon:20060328の日記でPythonでmp3のタグを取得するための方法を書いたが、実際fix_str関数は別のサイトのコピペなのでよく理解していなかった。最近XMLをいじることが多くUnicodeに関する知識が多少深まったおかげか今なら理解できることに気づいた。

def fix_str(s):
  try:
    #utf-8のunicode文字列を通常文字列に変換
    buf = "".join([chr(ord(x)) for x in s])
  except ValueError:
    #utf-16のunicode文字列が来たときはencodeで変換
    buf = s.encode("mbcs")
  return buf

PythonでいうUnicode文字列というのはutf-16UCS-2の文字列のことなので、上にある「utf-8unicode文字列」という表現は間違いで、正しくは「utf-8エンコードされた文字列」である。


@指摘を受けて追記
PythonにおけるUnicode文字列とはUCS-2またはUCS-4で、これはコンパイル時のオプションで決定される。UCS-2とは2バイトの文字集合であり、文字の表現方式であるutf-16とは違う。utf-16も基本的には1文字をUCS-2と同じコード体系の2バイトで表現するため今回は「たまたま」うまくいった。しかし、utf-16は1文字を4バイトで表現する可能性もあるため実は問題がある。そして、UCS-4でコンパイルされたPython(最近のLinuxに載っているのはこれらしい)では上手く動かないだろう。

参考リンク
http://www.python.org/doc/api/unicodeObjects.html
http://www.mylab.jp/diary/20060123.html

また、「unicode文字列が来たときはencodeで変換」以下の部分はとりあえずencode関数を使ったらうまくいったというだけで理解できていなかったが、encodeはUnicode文字列を指定した文字コードに変換して返すという関数なのでうまくいくというわけである。


しかし、chr(ord(x))の部分はいまだによくわからない。utf-8の文字列だけでなくShift-JISの文字もうまく処理できているようだけどなんなんだろうなぁ。まだ完全な理解には遠いらしい。