tl; dr /クイックフィックス
Python 2.xのUnicode Zen-ロングバージョン
ソースを確認しないと、根本的な原因を知るのは難しいので、一般的に説明する必要があります。
UnicodeDecodeError: 'ascii' codec can't decode byte
一般str
に、元の文字列のエンコーディングを指定せずに、非ASCIIを含むPython 2.x をUnicode文字列に変換しようとすると発生します。
簡単に言うと、Unicode文字列はエンコーディングをまったく含まない完全に別のタイプのPython文字列です。それらはUnicode ポイントコードのみを保持するため、スペクトル全体のあらゆるUnicodeポイントを保持できます。文字列には、UTF-8、UTF-16、ISO-8895-1、GBK、Big5などのエンコードされたテキストが含まれます。文字列はUnicodeにデコードされ、Unicodeは文字列にエンコードされます。ファイルとテキストデータは常にエンコードされた文字列で転送されます。
Markdownモジュールの作成者はおそらく、unicode()
(例外がスローされる場合)コードの残りの部分に対する品質ゲートとして使用します。ASCIIを変換するか、既存のUnicode文字列を新しいUnicode文字列に再ラップします。Markdownの作成者は受信文字列のエンコードを認識できないため、Markdownに渡す前に文字列をUnicode文字列にデコードする必要があります。
Unicode文字列はu
、文字列の接頭辞を使用してコードで宣言できます。例えば
>>> my_u = u'my ünicôdé strįng'
>>> type(my_u)
<type 'unicode'>
Unicode文字列は、ファイル、データベース、ネットワークモジュールから取得される場合もあります。これが発生した場合、エンコーディングについて心配する必要はありません。
ガチャ
からstr
Unicode への変換は、明示的にを呼び出さなくても発生する可能性がありますunicode()
。
次のシナリオではUnicodeDecodeError
例外が発生します。
# Explicit conversion without encoding
unicode('€')
# New style format string into Unicode string
# Python will try to convert value string to Unicode first
u"The currency is: {}".format('€')
# Old style format string into Unicode string
# Python will try to convert value string to Unicode first
u'The currency is: %s' % '€'
# Append string to Unicode
# Python will try to convert string to Unicode first
u'The currency is: ' + '€'
例
次の図でcafé
は、端末のタイプに応じて、単語が「UTF-8」または「Cp1252」のいずれかのエンコーディングでエンコードされている様子を確認できます。どちらの例でも、caf
は通常のASCIIです。UTF-8では、é
2バイトを使用してエンコードされます。「Cp1252」では、éは0xE9です(これはたまたまUnicodeポイント値です(偶然ではありません))。正しいものdecode()
が呼び出され、Python Unicodeへの変換が成功します。
この図でdecode()
は、はとともに呼び出されますascii
(これはunicode()
エンコードを指定せずに呼び出すのと同じです)。ASCIIにはより大きいバイトを含めることができないため0x7F
、これはUnicodeDecodeError
例外をスローします。
Unicodeサンドイッチ
コード内にUnicodeサンドイッチを形成することをお勧めします。この場合、すべての受信データをUnicode文字列にデコードし、Unicodeを処理してからstr
、途中でsにエンコードします。これにより、コードの途中で文字列のエンコードを心配する必要がなくなります。
入力/デコード
ソースコード
非ASCIIをソースコードに焼き付ける必要がある場合は、文字列の前にを付けてUnicode文字列を作成しますu
。例えば
u'Zürich'
Pythonがソースコードをデコードできるようにするには、ファイルの実際のエンコーディングと一致するエンコーディングヘッダーを追加する必要があります。たとえば、ファイルが「UTF-8」としてエンコードされている場合は、次を使用します。
# encoding: utf-8
これは、ソースコードに非ASCIIが含まれている場合にのみ必要です。
ファイル
通常、非ASCIIデータはファイルから受信されます。io
モジュールは、指定されたを使用して、その場で自分のファイルをデコードがTextWrapperを提供しますencoding
。ファイルには正しいエンコーディングを使用する必要があります-簡単に推測することはできません。たとえば、UTF-8ファイルの場合:
import io
with io.open("my_utf8_file.txt", "r", encoding="utf-8") as my_file:
my_unicode_string = my_file.read()
my_unicode_string
その後、Markdownに渡すのに適しています。行UnicodeDecodeError
からの場合は、read()
おそらく間違ったエンコーディング値を使用しています。
CSVファイル
Python 2.7 CSVモジュールは非ASCII文字をサポートしていませんsupport。ただし、ヘルプはhttps://pypi.python.org/pypi/backports.csvで入手できます。
上記のように使用しますが、開いたファイルをそれに渡します。
from backports import csv
import io
with io.open("my_utf8_file.txt", "r", encoding="utf-8") as my_file:
for row in csv.reader(my_file):
yield row
データベース
ほとんどのPythonデータベースドライバーはUnicodeでデータを返すことができますが、通常は少しの構成が必要です。SQLクエリには常にUnicode文字列を使用します。
MySQL
接続文字列に次を追加します。
charset='utf8',
use_unicode=True
例えば
>>> db = MySQLdb.connect(host="localhost", user='root', passwd='passwd', db='sandbox', use_unicode=True, charset="utf8")
PostgreSQL
追加:
psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
psycopg2.extensions.register_type(psycopg2.extensions.UNICODEARRAY)
HTTP
Webページは、ほぼすべてのエンコーディングでエンコードできます。Content-type
ヘッダが含まれている必要がありcharset
エンコーディングでヒントにフィールドを。次に、コンテンツをこの値に対して手動でデコードできます。または、Python-RequestsはでUnicodeを返しますresponse.text
。
手動で
文字列を手動でデコードする必要がある場合はmy_string.decode(encoding)
、単にを実行できます。ここencoding
で、は適切なエンコーディングです。Python 2.xでサポートされているコーデックは次のとおりです:標準エンコーディング。繰り返しにUnicodeDecodeError
なりますが、取得すると、おそらく間違ったエンコーディングを取得しています。
サンドイッチのお肉
通常のstrsと同じようにUnicodeを操作します。
出力
stdout /印刷
print
stdoutストリームを介して書き込みます。Pythonは、Unicodeがコンソールのエンコーディングにエンコードされるように、標準出力でエンコーダを構成しようとします。たとえば、Linuxシェルlocale
がのen_GB.UTF-8
場合、出力はにエンコードされUTF-8
ます。Windowsでは、8ビットのコードページに制限されます。
破損したロケールなど、コンソールの構成が正しくないと、予期しない印刷エラーが発生する可能性があります。PYTHONIOENCODING
環境変数は、標準出力のエンコーディングを強制できます。
ファイル
入力と同じように、io.open
Unicodeをエンコードされたバイト文字列に透過的に変換するために使用できます。
データベース
読み取りと同じ構成で、Unicodeを直接書き込むことができます。
Python 3
Python 3は、Python 2.xほどUnicodeに対応していませんが、このトピックの混乱はわずかです。たとえば、通常str
はUnicode文字列になり、古いものstr
は今bytes
です。
デフォルトのエンコーディングはUTF-8であるため.decode()
、エンコーディングを指定しないバイト文字列の場合、Python 3はUTF-8エンコーディングを使用します。これはおそらく人々のUnicode問題の50%を修正します。
さらに、open()
デフォルトではテキストモードで動作するため、デコードされたstr
もの(Unicodeのもの)を返します。エンコーディングはロケールから派生します。ロケールは、Un * xシステムではUTF-8、Windowsボックスでは8ビットコードページ(windows-1251など)になる傾向があります。
なぜ使用すべきではないのか sys.setdefaultencoding('utf8')
reload
問題を隠すだけで、Python 3.xへの移行を妨げる厄介なハックです(使用する理由があります)。問題を理解し、根本的な原因を修正して、Unicode Zenを楽しんでください。pyスクリプトでsys.setdefaultencoding( "utf-8")を使用してはならない理由を参照してください。詳細については