2009年11月19日

【UTF8文字幅揃え】unicodedata.east_asian_width()

 Python3からは利用文字コードはUTF-8が標準となることから、これ迄Python2上でShift_JISを文字コードとして指定することで出来た文字幅揃えが、全く出来なくなる。
 これはShift_JISの漢字文字コードがたまたま2バイトであることから、文字数(バイト数)=表示幅という相関性があり、それを流用していた為出来ていたことに過ぎない。

 過去、この問題に対し一度Shift_JIS化して処理する方法をとったことがあるが、これでは、Shift_JISに無い変換不能の文字を含んでいる場合に機能しないし、今後もShift_JIS規格に頼る様では何の為の国際化、UNICODE化なのか判らない。

 であるから、これに正面から向き合い対応するには、これからは、UTF-8で記述した文字が全角なのか半角なのか、それともそれ以外なのかを判別し処理する必要がある。それを行なう標準モジュールにある関数がunicodedata.east_asian_width()である。これはPython2.4以降で利用出来る。

 試しにこの関数に「あ1A」「@」「ア」「A1」等を入れて試ると「F」「W」「H」「Na」等の文字列を返してくる。
D:\>python
Python 2.6.2 (r262:71605, Apr 14 2009, 22:40:02) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import unicodedata
>>> unicodedata.east_asian_width(u'あ') #平仮名全角
'W'
>>> unicodedata.east_asian_width(u'ア') #片仮名全角
'W'
>>> unicodedata.east_asian_width(u'ア') #片仮名半角
'H'
>>> unicodedata.east_asian_width(u'1') #全角数字
'F'
>>> unicodedata.east_asian_width(u'1') #半角数字
'Na'
>>> unicodedata.east_asian_width(u'@') #機種依存文字
'A'
>>> unicodedata.east_asian_width(u'') #外字
'A'
>>> unicodedata.east_asian_width(u'𠮷') #UNICODE CJK拡張B(吉の異体字)まだ未対応なのかな??
Traceback (most recent call last):
File "", line 1, in
TypeError: need a single Unicode character as parameter
>>> unicodedata.east_asian_width(u'a')
'Na'
>>> unicodedata.east_asian_width(u'゛')
'W'
>>> unicodedata.east_asian_width(u'゙')
'H'
>>> unicodedata.east_asian_width(u'\u0633') #アラビア文字
'N'
詳細は「東アジアの文字列」を参照頂くと理解し易いが、我々東アジアの文字を含む文字列では、「F,W,A」を全角として「Na,H」を半角として扱うことになる。東アジア文字を全て含まない文字体系の場合には「Na,H,A」を半角つまりアルファベットと同等に扱い処理することになっている様で、それが為に、欧米系のシステムでは結果として出現しない東アジア文字について考慮されない場合がある様だ。

 実をいうとこのunicodedata.east_asian_width()はこのBlogで公開している「dvd_label.py」で使ってはいる。ただ、そのソースコードに書いてある通り、ネットからの拾物で、寸分違わずhush_puppyさんの「RubyとPythonで全角文字を半角文字2文字として数える」から理解することなく拝借させて頂いていただけ。
DVD_Label/dvd_label.py 113-144,646-647行より抜粋(タイトルを左寄揃えし次項目の開始位置を揃えた)


#####################################################################
#ネットからの拾いもの
#########################################################################################
## unicode下でのprint書式で全角半角幅の区別がないことでの桁揃えが出来ない不具合に対処 ##
#「RubyとPythonで全角文字を半角文字2文字として数える」(hush_puppyさん)より勝手に拝借 #
# http://d.hatena.ne.jp/hush_puppy/20090226/1235661269 #
# NICEですね。hush_puppyさんに心より御礼申上げます。 #
def ljust_kana(str, size, pad = " "): #
space = size - width_kana(str) #
if space > 0: #
str += pad * space #
return str #
def width_kana(str): #
all = len(str) # 全文字数 #
zenkaku = count_zen(str) # 全角文字数 #
hankaku = all - zenkaku # 半角文字数 #
return zenkaku * 2 + hankaku #
def count_zen(str): #
from unicodedata import east_asian_width #
n = 0 #
for c in str: #
wide_chars = u"WFA" #
eaw = east_asian_width(c) #
if wide_chars.find(eaw) > -1: #
n += 1 #
return n #
# もうひとつの解としてはUTF8をShift_JISに変換後print書式を通し再度UTF8に変換するとこも #
# 考えられるがUTF8=>Shift_JISがうまくいかないんだな。それに頻繁なコード変換は文字化け #
# 等の不具合発生の機会を増やすのでhush_puppyさんのアプローチが安全。ただ出来るなら #
# print書式そのものを全角対応にしたいのが本音だ。 #
## unicode下でのprint書式で全角半角幅の区別がないことでの桁揃えが出来ない不具合に対処 ##
#########################################################################################
<中略>
for d in datas:
print u"%5d %2d %s %s %8s" % (d[0],d[1],ljust_kana(d[2],64),d[3],d[4])
 

 hush_puppyさんの関数をそのまま使うことで、右寄せだろうと左寄せだろうと半角文字幅単位でのセンタリングも容易に対応出来るが、これをグローバルなものにするには、東アジア文字を含むシステムとして作成する場合とそうでない場合に分けて機能する様にするか、東アジア文字を含むことを前提にしたものをグロパルな規格として欧米中東言語地域の皆さんに認めてもらうしかないのでしょうね。「全角」って概念は漢字文化圏の活字文化生んだ産物で手書きの時代には東アジアでも関係なかったことだろうし、システム作成者の意図で切替え出来る方が良いのかもな。後は濃いお方にお任せ。


2010-05-11追記
関連として、UNICODE文字列の文字幅を返す関数 unicode_width(s, width={'Na':1, 'W':2, 'F':2, 'H':1, 'A':2, 'N':1}) を 「【Python でCGI】listを一覧表示(データ型変換と段落)」で掲載した。unicodedataの意味合いがより判り易いかも知れない。
posted by Mire at 17:46 | Comment(0) | TrackBack(0) | Pythonプログラミング | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
※ブログオーナーが承認したコメントのみ表示されます。

この記事へのトラックバック
月額見放題1,000円開始キャンペーンバナー(画像ありver)
紺碧の艦隊 ルパン三世 GREAT CHASE クリックプロモーション
<< 2013年01月 >>
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31    
カテゴリ
タグクラウド
ファン
利用中のオープンソース
最近のコメント
最近の記事
過去ログ
QRコード
レガシーなアプリはいかが?
Dell 法人のお客様ページ
  • 【法人様向け】デル、お得なキャンペーン情報
  • 法人のお客様向け ストレージソリューション
  • 法人のお客様向け ネットワークソリューション
  • 【SOHO法人様向け】デル・オンライン広告限定ページ
  • デル-個人のお客様ページ
  • 【個人のお客様向け】デル・オンライン広告限定ページ
  • オンライン広告限定キャンペーンページ
  • ソフトウェア&周辺機器 パソコン工房
    ツートップインターネットショップ(twotop.co.jp) マウスコンピューター/G-Tune
  • ×

    この広告は1年以上新しい記事の投稿がないブログに表示されております。