これを連結しようとすると、フィールドに「ñ」または「 ´」が含まれているとUnicodeDecodeErrorが発生します。 「ñ」または「 ´」を含むフィールドが最後の場合、エラーは発生しません。
#...
nombre = fabrica
nombre = nombre.encode("utf-8") + '-' + sector.encode("utf-8")
nombre = nombre.encode("utf-8") + '-' + unidad.encode("utf-8")
#...
return nombre
何か案が?どうもありがとう!
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値を直接処理しない場合)。
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')
Python3で実行するとこのエラーが発生しましたが、同じプログラムをpython2
で実行するだけで動作します