Python bite: 文字集合非対応文字の変換
Submitted by fujiwara on 2008, March 7 - 6:20pm.
Python 自体に咬まれたわけではないですが、 Python での実装中の話なので Python bite の括りで書きます。
入出力の文字集合体系(所謂「文字コード」) が一致している場合は問題無いのですが、 これらが一致していない場合、 出力文字コードが対応していない文字が入力に含まれていると咬まれます。
例えば Unicode の入力をベースに Shift_JIS の出力を生成するような場合、 '\uFF5E'(所謂「全角チルダ」)のような文字が使用されていると、 変換に失敗します。
% python
> import codecs
> import sys
> sys.stdout = codecs.getwriter('shift_jis')(sys.stdout)
> print u'\uff5e'
Traceback (most recent call last):
File "<stdin>", line 1, in ?
UnicodeEncodeError: 'shift_jis' codec can't encode
character u'\uff5e' in position 0:
illegal multibyte sequence
非対応文字の変換失敗
これは文字集合定義上の問題なので、 プログラムレベルでは根本的な解決はできません。
出来ることと言えば、 以下のような変換処理をはさむことで、 非対応文字を別な文字に変換してやることぐらいです (この変換テーブルでは不十分かもしれませんのでご注意ください) 。
convert_tuples = [
(u'\u00a6',u'\u007c'),#broken bar=>vertical bar
(u'\u2014',u'\u2015'),#horizontal bar=>em dash
(u'\u2225',u'\u2016'),#parallel to=>double vertical line
(u'\uff0d',u'\u2212'),#minus sign=>fullwidth hyphen minus
(u'\uff5e',u'\u301c'),#fullwidth tilde=>wave dash
(u'\uffe0',u'\u00a2'),#fullwidth cent sign=>cent sign
(u'\uffe1',u'\u00a3'),#fullwidth pound sign=>pound sign
(u'\uffe2',u'\u00ac'),#fullwidth not sign=>not sign
]
def unsafe2safe(string):
for unsafe, safe in convert_tuples:
string = string.replace(unsafe, safe)
return string
非対応文字の変換
Java の StringBuffer のような可変文字列を扱うクラスがある場合、 上記程度の変換テーブルサイズなら間違いなく 「対象文字列⇒変換テーブル」の入れ子構造にする (あるいはテーブル長と対象長の比較でループを切り替える )のですが、 Python では改変可能文字列クラスが無い (それともこういう場合は StringIO とかを使うのが一般的なのでしょうか? > Python ハッカー様)ため、 性能的にはちょっと嫌なループの組み方になっています。
なお、上記 unsafe2safe()
を適用するオブジェクトは
「Unicode 文字列」オブジェクトである必要があるため、
適宜事前処理してやる必要があるかもしれません。
Login to post comments