Kesalahan Enkode Unicode Python

104

Saya membaca dan mem-parsing file Amazon XML dan ketika file XML menunjukkan ', ketika saya mencoba untuk mencetaknya saya mendapatkan kesalahan berikut:

'ascii' codec can't encode character u'\u2019' in position 16: ordinal not in range(128) 

Dari apa yang saya baca secara online sejauh ini, kesalahan berasal dari fakta bahwa file XML ada dalam UTF-8, tetapi Python ingin menanganinya sebagai karakter yang dikodekan ASCII. Apakah ada cara sederhana untuk menghilangkan kesalahan dan meminta program saya mencetak XML saat dibaca?

Alex B
sumber
Saya baru saja datang ke SO untuk memposting pertanyaan ini. Apakah ada cara mudah untuk membersihkan string unicode()?
Nick Heiner
Periksa juga jawaban ini untuk pertanyaan terkait: "Python UnicodeDecodeError - Apakah saya salah paham tentang enkode?"
tzot

Jawaban:

193

Kemungkinan, masalah Anda adalah Anda menguraikannya dengan baik, dan sekarang Anda mencoba mencetak konten XML dan Anda tidak bisa melakukannya karena ada beberapa karakter Unicode asing. Coba encode string unicode Anda sebagai ascii terlebih dahulu:

unicodeData.encode('ascii', 'ignore')

bagian 'abaikan' akan memberitahunya untuk melewati karakter tersebut. Dari dokumen python:

>>> u = unichr(40960) + u'abcd' + unichr(1972)
>>> u.encode('utf-8')
'\xea\x80\x80abcd\xde\xb4'
>>> u.encode('ascii')
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
UnicodeEncodeError: 'ascii' codec can't encode character '\ua000' in position 0: ordinal not in range(128)
>>> u.encode('ascii', 'ignore')
'abcd'
>>> u.encode('ascii', 'replace')
'?abcd?'
>>> u.encode('ascii', 'xmlcharrefreplace')
'&#40960;abcd&#1972;'

Anda mungkin ingin membaca artikel ini: http://www.joelonsoftware.com/articles/Unicode.html , yang menurut saya sangat berguna sebagai tutorial dasar tentang apa yang terjadi. Setelah membaca, Anda akan berhenti merasa seperti Anda hanya menebak-nebak perintah apa yang harus digunakan (atau setidaknya yang terjadi pada saya).

Scott Stafford
sumber
1
Saya mencoba membuat string berikut ini aman: 'foo "bar bar" df' (perhatikan tanda kutip keriting), tetapi hal di atas masih gagal untuk saya.
Nick Heiner
@ Rosarch: Gagal bagaimana? kesalahan yang sama? Dan aturan penanganan kesalahan mana yang Anda gunakan?
Scott Stafford
@Rosarch, masalah Anda mungkin lebih awal. Coba kode ini: # - - coding: latin-1 - - u = u 'foo “bar bar” df' print u.encode ('ascii', 'ignore') Untuk Anda, ini mungkin mengubah string Anda menjadi unicode yang diberikan pengkodean yang Anda tentukan untuk skrip python yang menimbulkan kesalahan.
Scott Stafford
Saya melanjutkan dan membuat masalah saya menjadi pertanyaannya sendiri: stackoverflow.com/questions/3224427/…
Nick Heiner
1
.encode('ascii', 'ignore')kehilangan data secara tidak perlu meskipun lingkungan OP mungkin mendukung karakter non-ascii (kebanyakan kasus)
jfs
16

Solusi yang lebih baik:

if type(value) == str:
    # Ignore errors even if the string is not proper UTF-8 or has
    # 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)

Jika Anda ingin membaca lebih lanjut tentang mengapa:

http://docs.plone.org/manage/troubleshooting/unicode.html#id1

Paxwell
sumber
3
Ini tidak membantu dengan masalah OP: "tidak dapat menyandikan karakter u '\ u2019'" . u'\u2019sudah Unicode.
jfs
6

Jangan melakukan hardcode pengkodean karakter lingkungan Anda di dalam skrip Anda; cetak teks Unicode secara langsung sebagai gantinya:

assert isinstance(text, unicode) # or str on Python 3
print(text)

Jika output Anda diarahkan ke file (atau pipa); Anda bisa menggunakan PYTHONIOENCODINGenvvar, untuk menentukan pengkodean karakter:

$ PYTHONIOENCODING=utf-8 python your_script.py >output.utf8

Jika tidak, python your_script.pyharus bekerja seperti - pengaturan lokal Anda digunakan untuk mengkodekan teks (pada POSIX cek: LC_ALL, LC_CTYPE, LANGenvvars - set LANGke utf-8 lokal jika diperlukan).

Untuk mencetak Unicode di Windows, lihat jawaban ini yang menunjukkan cara mencetak Unicode ke konsol Windows, ke file, atau menggunakan IDLE .

jfs
sumber
1

Pos luar biasa: http://www.carlosble.com/2010/12/understanding-python-and-unicode/

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

def __if_number_get_string(number):
    converted_str = number
    if isinstance(number, int) or \
            isinstance(number, float):
        converted_str = str(number)
    return converted_str


def get_unicode(strOrUnicode, encoding='utf-8'):
    strOrUnicode = __if_number_get_string(strOrUnicode)
    if isinstance(strOrUnicode, unicode):
        return strOrUnicode
    return unicode(strOrUnicode, encoding, errors='ignore')


def get_string(strOrUnicode, encoding='utf-8'):
    strOrUnicode = __if_number_get_string(strOrUnicode)
    if isinstance(strOrUnicode, unicode):
        return strOrUnicode.encode(encoding)
    return strOrUnicode
Ranvijay Sachan
sumber
0

Anda dapat menggunakan sesuatu dari formulir

s.decode('utf-8')

yang akan mengubah bytestring berenkode UTF-8 menjadi string Unicode Python. Tetapi prosedur yang tepat untuk digunakan bergantung pada bagaimana Anda memuat dan mengurai file XML, misalnya jika Anda tidak pernah mengakses string XML secara langsung, Anda mungkin harus menggunakan objek dekoder dari codecsmodul .

David Z
sumber
Ini sudah dikodekan dalam UTF-8. Kesalahannya khususnya: myStrings = deque (teks [u'Dorf dan Svoboda \ u2019s dibangun di atas subdisiplin str ... dan Teknik Komputer \ u2019s. ']) String ada dalam UTF-8 sebagai Anda bisa lihat, tetapi marah tentang internal '\ u2019'
Alex B
Oh, oke, saya pikir Anda mengalami masalah lain.
David Z
7
@ Alex B: Tidak, stringnya adalah Unicode, bukan Utf-8. Untuk menyandikannya sebagai penggunaan Utf-8'...'.encode('utf-8')
sth
0

Saya menulis yang berikut ini untuk memperbaiki kutipan non-ascii gangguan dan memaksa konversi ke sesuatu yang dapat digunakan.

unicodeToAsciiMap = {u'\u2019':"'", u'\u2018':"`", }

def unicodeToAscii(inStr):
    try:
        return str(inStr)
    except:
        pass
    outStr = ""
    for i in inStr:
        try:
            outStr = outStr + str(i)
        except:
            if unicodeToAsciiMap.has_key(i):
                outStr = outStr + unicodeToAsciiMap[i]
            else:
                try:
                    print "unicodeToAscii: add to map:", i, repr(i), "(encoded as _)"
                except:
                    print "unicodeToAscii: unknown code (encoded as _)", repr(i)
                outStr = outStr + "_"
    return outStr
pengguna5910
sumber
0

Jika Anda perlu mencetak representasi perkiraan dari string ke layar, daripada mengabaikan karakter yang tidak dapat dicetak itu, coba unidecodepaket di sini:

https://pypi.python.org/pypi/Unidecode

Penjelasannya ditemukan di sini:

https://www.tablix.org/~avian/blog/archives/2009/01/unicode_transliteration_in_python/

Ini lebih baik daripada menggunakan u.encode('ascii', 'ignore')untuk string tertentu u, dan dapat menyelamatkan Anda dari sakit kepala yang tidak perlu jika presisi karakter bukanlah yang Anda cari, tetapi tetap ingin memiliki keterbacaan manusia.

Wirawan

Wirawan Purwanto
sumber
-1

Coba tambahkan baris berikut di bagian atas skrip python Anda.

# _*_ coding:utf-8 _*_
abnormal
sumber
-1

Python 3.5, 2018

Jika Anda tidak tahu apa yang dienkode tetapi pengurai unicode mengalami masalah, Anda dapat membuka file di Notepad++dan di pilih bilah atas Encoding->Convert to ANSI. Kemudian Anda bisa menulis python Anda seperti ini

with open('filepath', 'r', encoding='ANSI') as file:
    for word in file.read().split():
        print(word)
Atomar94
sumber