Python Unicode Kodlama Hatası


104

Bir Amazon XML dosyasını okuyup ayrıştırıyorum ve XML dosyası bir 'gösterirken, onu yazdırmaya çalıştığımda şu hatayı alıyorum:

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

Şimdiye kadar çevrimiçi okuduğumdan, hata XML dosyasının UTF-8'de olmasından kaynaklanıyor, ancak Python bunu ASCII kodlu bir karakter olarak ele almak istiyor. Hatayı ortadan kaldırmanın ve programımın XML'i okurken yazdırmasını sağlamanın basit bir yolu var mı?


SO'ya bu soruyu göndermek için geliyordum. Bir ipi sterilize etmenin kolay bir yolu var mı unicode()?
Nick Heiner

Lütfen ilgili soruya şu yanıtı da kontrol edin : "Python UnicodeDecodeError - Kodlamayı yanlış mı anlıyorum?"
tzot

Yanıtlar:


193

Muhtemelen, probleminiz, onu iyi bir şekilde ayrıştırmış olmanızdır ve şimdi XML'in içeriğini yazdırmaya çalışıyorsunuz ve bazı yabancı Unicode karakterleri olduğundan yapamıyorsunuz. Unicode dizenizi önce ascii olarak kodlamayı deneyin:

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

'göz ardı etme' bölümü, ona sadece bu karakterleri atlamasını söyleyecektir. Python belgelerinden:

>>> 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;'

Bu makaleyi okumak isteyebilirsiniz: http://www.joelonsoftware.com/articles/Unicode.html , neler olup bittiğine dair temel bir öğretici olarak çok yararlı buldum. Okuduktan sonra, hangi komutları kullanacağınızı tahmin ediyormuş gibi hissetmeyi bırakacaksınız (ya da en azından benim başıma geldi).


1
Aşağıdaki dizeyi güvenli hale getirmeye çalışıyorum: 'foo "bar bar" df' (kıvrık tırnaklara dikkat edin), ancak yukarıdaki hala benim için başarısız oluyor.
Nick Heiner

@Rosarch: Nasıl başarısız olur? aynı hata? Ve hangi hata işleme kuralını kullandınız?
Scott Stafford

@Rosarch, probleminiz muhtemelen daha erken. Bu kodu deneyin: # - - kodlama: latin-1 - - u = u 'foo “bar bar” df' print u.encode ('ascii', 'ignore') Sizin için muhtemelen INTO unicode dizesini dönüştürüyordu hatayı veren python komut dosyası için belirttiğiniz kodlama.
Scott Stafford

Devam ettim ve sorunumu kendi sorusuna
çevirdim

1
.encode('ascii', 'ignore')OP'nin ortamı ascii olmayan karakterleri desteklese bile verileri gereksiz yere kaybeder (çoğu durumda)
jfs

16

Daha iyi bir çözüm:

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)

Nedeniyle ilgili daha fazla okumak isterseniz:

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


3
OP'nin sorununa yardımcı olmuyor: "u '\ u2019' karakteri kodlanamıyor" . u'\u2019zaten Unicode.
jfs

6

Ortamınızın karakter kodlamasını komut dosyanızın içine kodlamayın; bunun yerine Unicode metnini doğrudan yazdırın:

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

Çıktınız bir dosyaya (veya bir boruya) yeniden yönlendirilirse; PYTHONIOENCODINGkarakter kodlamasını belirtmek için envvar kullanabilirsiniz :

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

Aksi takdirde, python your_script.pyolarak çalışması gerekir hazır - yerel ayarları metin kodlamak için kullanılır (POSIX çeke: LC_ALL, LC_CTYPE, LANGEnvvars - set LANGbir utf-8 yerel ayara gerekirse).

Windows'ta Unicode yazdırmak için, Unicode'un Windows konsoluna, bir dosyaya veya IDLE kullanılarak nasıl yazdırılacağını gösteren bu yanıta bakın .


1

Mükemmel gönderi: 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

0

Formdaki bir şeyi kullanabilirsin

s.decode('utf-8')

test edilerek kodlanmış UTF-8'i bir Python Unicode dizesine dönüştürür. Ancak kullanılacak kesin prosedür, XML dosyasını tam olarak nasıl yükleyip ayrıştırdığınıza bağlıdır; örneğin, XML dizesine doğrudan erişmezseniz, codecsmodülden bir kod çözücü nesnesi kullanmanız gerekebilir .


Zaten UTF-8'de kodlanmıştır Hata özellikle: myStrings = deque ([u'Dorf ve Svoboda \ u2019s metni str ... ve Bilgisayar Mühendisliği \ u2019s alt disiplinleri üzerine inşa edilir. ']) Dize şu şekilde UTF-8'de görebiliyorsunuz, ancak dahili "\ u2019" yüzünden çıldırıyor
Alex B

Tamam, farklı bir sorunun olduğunu sanıyordum.
David Z

7
@Alex B: Hayır, dize Unicode, Utf-8 değil. To kodlamak Utf-8 kullanım olarak'...'.encode('utf-8')
sth

0

Ascii olmayan rahatsız edici alıntıları düzeltmek ve kullanılabilir bir şeye dönüştürmeye zorlamak için aşağıdakileri yazdım.

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

0

Dizenin yaklaşık bir temsilini ekrana yazdırmanız gerekiyorsa, bu yazdırılamayan karakterleri yok saymak yerine lütfen unidecodeburada paketlemeyi deneyin :

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

Açıklama burada bulunur:

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

Bu, u.encode('ascii', 'ignore')belirli bir dizge için kullanmaktan daha iyidir uve eğer karakter kesinliği peşinde olduğunuz şey değilse, ancak yine de insan tarafından okunabilirlik istiyorsanız sizi gereksiz baş ağrısından kurtarabilir.

Wirawan


-1

Aşağıdaki satırı python betiğinizin üstüne eklemeyi deneyin.

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

-1

Python 3.5, 2018

Kodlamanın ne olduğunu bilmiyorsanız, ancak unicode ayrıştırıcısının sorun yaşadığını bilmiyorsanız, dosyayı açabilirsiniz Notepad++ve üst çubuktan öğesini seçin Encoding->Convert to ANSI. O zaman python'unu böyle yazabilirsin

with open('filepath', 'r', encoding='ANSI') as file:
    for word in file.read().split():
        print(word)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.