使用するとき
fh = codecs.open(fname,'r','utf8')
fh.read()ユニコードを返します。このユニコードを取得し、データベース ドライバー (mysql-python など) を使用してデータベースにデータを挿入する場合、ドライバーはユニコードをバイトに変換する必要があります。ドライバーは、によって設定されたエンコードを使用しています
con.set_character_set('utf8')
使用する場合
fh = open(fname, 'r')
次にfh.read()、バイト文字列を返します。たまたま入っていたバイトに翻弄されfnameます。幸いなことに、あなたの投稿によると、ファイルは UTF-8 でエンコードされています。データはすでにバイト文字列であるため、ドライバーはエンコードを実行せず、単にバイト文字列をそのままデータベースに通信します。
いずれにしても、UTF-8 でエンコードされたバイトの同じ文字列がデータベースに挿入されます。
codecs.openを定義するソース コードを見てみましょう。
def open(filename, mode='rb', encoding=None, errors='strict', buffering=1):
if encoding is not None:
if 'U' in mode:
# No automatic conversion of '\n' is done on reading and writing
mode = mode.strip().replace('U', '')
if mode[:1] not in set('rwa'):
mode = 'r' + mode
if 'b' not in mode:
# Force opening of the file in binary mode
mode = mode + 'b'
file = __builtin__.open(filename, mode, buffering)
if encoding is None:
return file
info = lookup(encoding)
srw = StreamReaderWriter(file, info.streamreader, info.streamwriter, errors)
# Add attributes to simplify introspection
srw.encoding = encoding
return srw
encoding特に、noが設定されている場合に何が起こるかに注意してください。
file = __builtin__.open(filename, mode, buffering)
if encoding is None:
return file
エンコーディングが設定されていない場合はcodecs.open、基本的にビルトインと同じです。openビルトインは、メソッドがstropenオブジェクトを返すファイル オブジェクトを返します。デコードは一切行いません。read
対照的に、エンコーディングを指定すると、に設定されcodecs.openた が返されます。のメソッドを呼び出すと、通常、 Unicodeオブジェクトが返されます。最初に、指定されたエンコーディングを使用してstrオブジェクトをデコードする必要があります。StreamReaderWritersrw.encodingencodingStreamReaderWriterread
あなたの例では、strオブジェクトは
In [19]: content
Out[19]: '\xe2\x80\x9cThank you.\xe2\x80\x9d'
エンコーディングを として指定すると、 はエンコーディング'ascii'を使用しStreamReaderWriterてデコードを試みます。content'ascii'
In [20]: content.decode('ascii')
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 0: ordinal not in range(128)
asciiエンコーディングでは 0 ~ 127 の範囲のバイトしかデコードできず'\xe2'、 の最初のバイトでcontentある にはその範囲外の序数値があるため、これは驚くべきことではありません。
具体的には:エンコーディングを指定しない場合:
In [13]: with codecs.open(filename, 'r') as f:
....: content = f.read()
In [14]: content
Out[14]: '\xe2\x80\x9cThank you.\xe2\x80\x9d'
contentですstr。
有効なエンコーディングを指定すると:
In [22]: with codecs.open(filename, 'r', encoding = 'utf-8') as f:
....: content = f.read()
In [23]: content
Out[23]: u'\u201cThank you.\u201d'
contentですunicode。
無効なエンコーディングを指定した場合:
In [25]: with codecs.open(filename, 'r', 'ascii') as f:
....: content = f.read()
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 0: ordinal not in range(128)
を取得しUnicodeDecodeErrorます。