ユニコードの符号化と復号化

はじめに: なぜユニコードが難しいのか?

Python 2.x では、以下2つをきちんと区分けして作られていない。

  • 8ビットストリング (バイトデータ)
  • 16ビットユニコードストリング (文字データ)

開発者は、2つの交換( 変換? )可能な形式を使うことになる。なぜなら、それは簡単で、Pythonはそれについて警告をしないからである。

しかしながら、国際的な(non-ASCII)文字列の入力に遭遇しなければ動作するだろう。 8ビットエンコードストリングと直の16ビットユニコードストリングが 最初のエンコーディングを通じ混合している時、本当に扱いにくい物事が起こり始める。 全然うまく訳せない

追加情報(英語):

sys.setdefaultencoding()

Python has system-wide setting to enforce encoding of all unicode input automatically to utf-8 when used as 8-bit string.

Pythonは、 8ビットストリングを使うときに自動で全てのユニコードの文字コードを システム全体 の設定強要することが出来る。

警告

これは、間違って物事を解決することで、他の物をこわすことになります。 これは警告です。

UnicodeEncodeError

UnicodeEncodeError: ‘ascii’ codec can’t encode character u’xe4’ in position 4: ordinal not in range(128)

これは通常、ユニコードデータの出力やストア(保存)する時に、 archaid?? ??

  • 印刷
  • ロギング(logging)
  • 7ビットID

以下の代わりに:

print foo

以下のようにする:

print foo.encode("utf-8") # これはユニコードストリングとして

フィルタリングの例:

def safe_print(x):
        """ Do not die on bad input when doing debug prints """
        if type(x) == str:
                print x
        else:
                print x.decode("utf-8")

UnicodeDecodeError

安全にデコードする方法

unicode strings.

この例は、全てストリング入力を受け取り、正しいユニコードストリングにそれらを変換する

例:

if type(value) == str:
        # Ignore errors even if the string is not proper UTF-8 or have broken marker bytes
        # Python built-in function unicode() can do this.
        value = unicode(value, "utf-8", errors="ignore")
else:
    # Assume the value object has proper __unicode__() method
value = unicode(value)

悪名高きnon-breakingユニコードスペース (\xa0)

Linux上でCTRL+スペース / Altスペースを偶然に使うと作られる。

見つけることが出来ない が、あらゆる物を壊す。

修正方法

Example to how to fix non-breaking spacebar characters which have ended up to reST .txt files. This is Unicode character code A0.

non-breakingスペースバー文字列の修正し最後はreSTの.txtファイルにする方法例。 これは、ユニコードキャラクターコード A0である。

例 fix_wtf_space.py:

# -*- coding: utf-8 -*-
"""

    Fix non-breaking spacebar characters which have ended up to reST .txt files.
    This is Unicode character code A0.

    Press CTRL+space / AltGr space on Linux to accidentally create it.


    E.g. as a sympton the following exception is raised if you try
    to upload Python egg::

          File "/Library/Python/2.6/site-packages/docutils-0.6-py2.6.egg/docutils/parsers/rst/states.py", line 2621, in blank
            self.parent += self.literal_block()
          File "/Library/Python/2.6/site-packages/docutils-0.6-py2.6.egg/docutils/parsers/rst/states.py", line 2712, in literal_block
            literal_block = nodes.literal_block(data, data)
          File "/Library/Python/2.6/site-packages/docutils-0.6-py2.6.egg/docutils/nodes.py", line 810, in __init__
            TextElement.__init__(self, rawsource, text, *children, **attributes)
          File "/Library/Python/2.6/site-packages/docutils-0.6-py2.6.egg/docutils/nodes.py", line 798, in __init__
            textnode = Text(text)
          File "/Library/Python/2.6/site-packages/docutils-0.6-py2.6.egg/docutils/nodes.py", line 331, in __new__
            return reprunicode.__new__(cls, data)
        UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 715: ordinal not in range(128)


"""

import os


def fix(name):
    """ Fix a single .TXT file
    """
    input = open(name, "rt")
    text = input.read()
    input.close()
    text = text.decode("utf-8")

    # Show if we get bad hits
    for c in text:
        if c == u"\xa0":
            print "Ufff"

    text = text.replace(u"\xa0", u" ")

    text = text.encode("utf-8")

    output = open(name, "wt")
    output.write(text)
    output.close()


# Process all .txt files in the
# current folder
for f in os.listdir(os.getcwd()):
    if f.endswith(".txt"):
        fix(f)