日本語文字の扱いについて

pythonに限らず、文字コード問題は常に悩ましい問題となる。

windows用のpythonを書いているときに遭遇した悩ましい問題について書いておこうと思う。

まだ自分のコードが完全動作していないので、間違いがあるかもしれないのでその点は指摘していただければ幸いだ。

試している環境は、"Python 2.7 (r27:82525, Jul 4 2010, 09:01:59) [MSC v.1500 32 bit (Intel)] on win32."

例えば、こんな場合に問題にぶち当たる。

windowsで日本語を含むファイルの名前を取得しようとたが、なぜか帰ってくる値が途中でぶった切られている。

コード的にはこんな感じ

# -*- coding: UTF-8 -*-
#-------------------------------------------------------------------------------
# Name:        blog demo code
# Purpose:
#
# Author:      earth
#
# Created:     30/10/2010
# Copyright:   (c) earth 2010
#-------------------------------------------------------------------------------
#!/usr/bin/env python

import sys
import os

def main():
    path=sys.argv[1]
    print os.path.basename(path)

if __name__ == '__main__':
    main()

第一引数に与えられたファイルのフルパスから、ファイル名だけを抜き出す、ほぼ2行の簡単なコードです。

日本語を含むファイルを引数で与えても、大抵の場合は問題になりません。
問題が起こっても、エラーは出ないので、出力しない場合は気がつかないことも考えられます。


上記のコードで問題が出るのは、下記のような場合です。

C:\test>blogdemocode.py j:\イソジン.txt
ジン.txt

ファイル名だけを取得するはずですが、ジン.txtという文字列が帰ってきています。
期待した値ではないですが、エラーは出ません。


上記のコードは、Shift_JISの"ソ"を構成している、835Cの後半、5Cの部分を、\として解釈します。

s.path.basename(path)は、pathの文字列を後ろから区切り文字(\)がある場所まで追っていきます。


つまり、 t x t . ン ジ と追ってきたあと、ソの中に含まれている\を区切り文字として解釈した時点で、そこまでの文字列をファイル名として返します。

結果として、ジン.txtがファイル名として帰ってきます。

一番手っ取り早い解決策はおそらくこれでしょう。

def main():
    path=sys.argv[1]
    path=unicode(path,"mbcs")
    print os.path.basename(path)

最初のコードからの変更点は、 path=unicode(path,"mbcs")の部分です。
os.path.basenameに処理させる前に、Unicode文字列に変えてしまうのです。

unicode(str,"mbcs")
文字コード"mbcs"の文字列strをunicodeに変換。

str.encode("mbcs")
文字列strを"mbcs"に変換。

実用的な使い方は、機能のエントリー、"ftpにファイルをアップロードする"のコードを見てください。