付録 A: Unicode and Python 2.7.x
今回 Python 2 にて Unicode の処理をする必要が生じた.これは日本語の Web page やドイツ語の Web page の処理のためである.実際には英語の Web pageにも accent のある文字が出現することがあるので,Unicode は避けて通れなかった.プログラムの開発中に,UnicodeDecodeError と UnicodeEncodeError というexception に悩まされたので,これを解説しておく.
How the Unicode encodes characters?
Unicode は私の理解するところ,2つの map を使う coding system である.これはどのようにこの体系を理解するかにもよる.私はこの調査をするまではこのことを知らなかったので UTF-8 などという coding system があると誤解していた.UTF-8 というのは Unicode をどのように codeするのかという mapping の手法の一つであって,Unicode そのものではない.
- Unicode: a map from characters to code (numbers)
- UTF-X: a map from Unicode encoded data to a specific data
Unicode そのものは code point と呼ばれる番号と文字の Description の単一のmapである.たとえば. 0x0061 'a'; LATIN SMALL LETTER A である.ここで0x0061 という数字が code point である.これが font に map されると,図形としての文字が表示される.図形としての文字は glyph と呼ばれる.Unicodeのmap は bijection であるので,文字 a は code point 0x0061 へmap されるとも言える.
この code point が Unicode,つまりある数を特定の文字への code している.しかし通常この Unicode の code point は使われない.通常使われないという意味は,テキストファイルにこの番号が save されることはまずないということである.通常もう一つの map,Unicode Transformation Format (UTF)が使われる.UTF-8, UTF-16 と endian information などが存在する.実際にはこのtransformation format に encode されたバイト列がファイルに save される.私はこのような用法が一般なので Unicode は Uni の code ではないと考えていた.Unicode の coding そのものは唯一であるが,それを実際に使う時のmapping が複数あるという意味では Uni ではない.したがって,Unicode はUni な code であるが,UTF-8, UTF-16 などは複数ある mapping の一つである.これは Unicode をそのまま使った場合に英語の Text などのサイズが増大する問題を避けるために生じた問題である.
これらの知識は [2] によった.
Python 2.7.x's Unicode representation
Python 2.x において文字列を表現するデータ型としては str 型と unicode 型がある.str 型は 8-bit の任意のデータ保持できるが,より ASCII の処理に適している.それぞれのデータ型は異なる encode への変換が可能である [2].
では,結局ほとんど同じであるのならば,文字列という一つのコンセプトを表現するために,なぜ違うデータ型が存在するのであろうか.これはおそらく歴史的な理由で,初期の python は Unicode のサポートをしていなかったため,2つのデータ型ができてしまったようである.実際,Python 3 では str 型が Unicodeを直接内部で利用可能なために,この違いはなくなっているようである.
Python 2.7 ではしかし,これが print (stream) に渡る時に問題を引き起こすことがある.Python 2.7.xにおける encode とdecode, そして文字型間の関係を図 8に示す.
Figure 8: Relationship between Unicode type and 8-bit str type in Python 2.7.x. |
まずは unicode 型の文字列を定義する.
uc = u'Wächter'
print type(uc)
-> <type 'unicode'>
これを utf-8 で str 型に encode する.
s = uc.encode('utf-8', 'ignore')
print type(s)
-> <type 'str'>
print statement は str をとるので,unicode 型が与えられると encode が呼ばれる.
print ucuc には ascii に encode できない文字が含まれているので,error が発生した.ここで発生した error は encode の error であることに注意すること.
-> UnicodeEncodeError: 'ascii'
codec can't encode character
u'\xe4' in position 1: ordinal
not in range(128)
しかし,error を無視するように指定して encode を行えばこれは機能する.
print uc.encode('utf-8', 'ignore')
-> 'Wächter'
複雑な case としては,encode された str 型がまた decode される場合がある.
print u'{0}'.format(uc.encode('utf-8', 'ignore'))
-> UnicodeDecodeError: 'ascii'
codec can't decode byte 0xc3 in
position 1: ordinal not in
range(128)
ここでは format が str 型をとったが,それが unicode 型に対するものであったので,decode が呼ばれた.しかし,そこには decode の 'ascii' が扱えない文字が入っていたため exception が発生した.ここでは encode exceptionではないことに注意されたい.したがって,次のように最後に encode する場合にはこれは機能する.
print u'\{0\}'.format(uc).
encode('utf-8', 'ignore')
-> Wächter
付録 B: Contribution to Wikipedia
今回の実験の副作用として Wikipedia にある List の間違いが判明したので,これを修正し,Wikipedia への貢献を行なった.
今回の実験では隣接行列を生成し,eigenanalysis を用いてその行列を解析した.eigenanalysis では matrix の basis が独立していることが望ましい.しかし,今回のような matrix では一般には full rank のmatrix は望めない.たとえば,著者へのリンクのない著者の Page やリンクが張られていない page, root nodeからの同じpage への linkなどの間違いが避けられないからである.PageRank アルゴリズムはこれに対処する方法が組込まれているが,root node のリンクの間違いは簡単に修正できるので,ここではduplicated link の check を行い,それを除いた.
Duplicated link は間違いもあるが,Pseudonym が link されている場合もあるので目視でそのチェックを行なった.
Wikipedia への貢献が行えたことは個人的に嬉しい.
Comments
Post a Comment