web-dev-qa-db-ja.com

UnicodeDecodeError: 'ascii'コーデックは23の位置にあるバイト0xc3をデコードできません:順序が範囲外(128)

これを連結しようとすると、フィールドに「ñ」または「 ´」が含まれているとUnicodeDecodeErrorが発生します。 「ñ」または「 ´」を含むフィールドが最後の場合、エラーは発生しません。

#...

nombre = fabrica
nombre = nombre.encode("utf-8") + '-' + sector.encode("utf-8")
nombre = nombre.encode("utf-8") + '-' + unidad.encode("utf-8")

#...

return nombre 

何か案が?どうもありがとう!

45
Capens

UTF-8にエンコードしてから、re-encoding to UTF-8。 Pythonは、最初にdecodesをUnicodeに戻す場合にのみこれを行うことができますが、デフォルトのASCIIコーデックを使用する必要があります。

>>> u'ñ'
u'\xf1'
>>> u'ñ'.encode('utf8')
'\xc3\xb1'
>>> u'ñ'.encode('utf8').encode('utf8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)

エンコードを続けないでください。代わりにエンコーディングをUTF-8 可能な限り最後までのままにしてください。代わりにUnicode値を連結します。

ここでstr.join()(または、むしろunicode.join())を使用して、3つの値をダッシュ​​で連結できます:

nombre = u'-'.join(fabrica, sector, unidad)
return nombre.encode('utf-8')

ただし、ここでのエンコードも早すぎる可能性があります。

経験則:値を受け取った瞬間をデコードし(既にAPIによって提供されているUnicode値でない場合)、必要な場合にのみエンコードします(宛先APIがUnicode値を直接処理しない場合)。

55
Martijn Pieters

UnicodeEncodeErrorを取得すると、コードのどこかでバイト文字列をUnicode文字列に直接変換することを意味します。 Python 2のデフォルトでは、ASCIIエンコーディングとPython3のutf8エンコーディングを使用します(いずれのエンコーディングでもすべてのバイトが有効ではないため、両方とも失敗する可能性があります)

これを回避するには、明示的なデコードを使用する必要があります。

入力ファイルに2つの異なるエンコーディングがある場合、そのうちの1つは任意のバイト(UTF8とLatin1など)を受け入れます。UnicodeDecodeErrorが発生した場合、最初に文字列を最初に変換し、2番目の文字列を使用できます。

def robust_decode(bs):
    '''Takes a byte string as param and convert it into a unicode one.
First tries UTF8, and fallback to Latin1 if it fails'''
    cr = None
    try:
        cr = bs.decode('utf8')
    except UnicodeDecodeError:
        cr = bs.decode('latin1')
    return cr

元のエンコーディングがわからず、非ASCII文字を気にしない場合は、errorsメソッドのオプションのdecodeパラメーターをreplaceに設定できます。問題のあるバイトは置き換えられます(標準ライブラリのドキュメントから):

適切な置換文字で置換します。 Pythonは、デコード時の組み込みUnicodeコーデックおよびエンコード時の「?」に公式のU + FFFD置換文字を使用します。

bs.decode(errors='replace')
7
Serge Ballesta

Python3で実行するとこのエラーが発生しましたが、同じプログラムをpython2で実行するだけで動作します

0
Jose Kj