ข้อผิดพลาดการเข้ารหัส Python Unicode


105

ฉันกำลังอ่านและแยกวิเคราะห์ไฟล์ Amazon XML และในขณะที่ไฟล์ XML แสดงเครื่องหมาย 'เมื่อฉันพยายามพิมพ์ฉันได้รับข้อผิดพลาดต่อไปนี้:

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

จากสิ่งที่ฉันอ่านทางออนไลน์จนถึงตอนนี้ข้อผิดพลาดเกิดจากข้อเท็จจริงที่ว่าไฟล์ XML อยู่ใน UTF-8 แต่ Python ต้องการจัดการเป็นอักขระที่เข้ารหัส ASCII มีวิธีง่ายๆในการทำให้ข้อผิดพลาดหายไปและให้โปรแกรมของฉันพิมพ์ XML ตามที่อ่านหรือไม่


ฉันเพิ่งมาที่ SO เพื่อโพสต์คำถามนี้ มีวิธีง่ายๆในการฆ่าเชื้อสตริงunicode()หรือไม่?
Nick Heiner

โปรดตรวจสอบคำตอบนี้สำหรับคำถามที่เกี่ยวข้อง:“ Python UnicodeDecodeError - ฉันเข้าใจผิดในการเข้ารหัสหรือไม่”
tzot

คำตอบ:


194

เป็นไปได้ว่าปัญหาของคุณคือคุณแยกวิเคราะห์ได้แล้วและตอนนี้คุณกำลังพยายามพิมพ์เนื้อหาของ XML แต่ไม่สามารถทำได้เนื่องจากมีอักขระ Unicode แปลกปลอมอยู่ ลองเข้ารหัสสตริง Unicode ของคุณเป็น ascii ก่อน:

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

ส่วน "ละเว้น" จะบอกให้ข้ามอักขระเหล่านั้นไป จากเอกสาร 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;'

คุณอาจต้องการอ่านบทความนี้: http://www.joelonsoftware.com/articles/Unicode.htmlซึ่งฉันพบว่ามีประโยชน์มากในการสอนขั้นพื้นฐานเกี่ยวกับสิ่งที่เกิดขึ้น หลังจากอ่านแล้วคุณจะหยุดรู้สึกว่าคุณแค่เดาคำสั่งที่จะใช้ (หรืออย่างน้อยก็เกิดขึ้นกับฉัน)


1
ฉันพยายามทำให้สตริงต่อไปนี้ปลอดภัย: 'foo“ bar bar” df' (สังเกตเครื่องหมายคำพูดแบบโค้ง) แต่ข้างต้นยังคงล้มเหลวสำหรับฉัน
Nick Heiner

@Rosarch: ล้มเหลวได้อย่างไร? ข้อผิดพลาดเดียวกัน? และคุณใช้กฎการจัดการข้อผิดพลาดใด
Scott Stafford

@Rosarch ปัญหาของคุณน่าจะเร็วกว่านี้ ลองใช้รหัสนี้: # - - การเข้ารหัส: latin-1 - - u = u 'foo“ bar bar” df' พิมพ์ u.encode ('ascii', 'ไม่สนใจ') สำหรับคุณมันอาจจะเป็นการแปลงสตริงของคุณให้เป็น Unicode ที่กำหนด การเข้ารหัสที่คุณระบุสำหรับ python scrip ที่ทำให้เกิดข้อผิดพลาด
Scott Stafford

ฉันดำเนินการต่อและทำให้ปัญหาเป็นคำถามของตัวเอง: stackoverflow.com/questions/3224427/…
Nick Heiner

1
.encode('ascii', 'ignore')สูญเสียข้อมูลโดยไม่จำเป็นแม้ว่าสภาพแวดล้อมของ OP อาจรองรับอักขระที่ไม่ใช่ ascii (กรณีส่วนใหญ่)
jfs

16

ทางออกที่ดีกว่า:

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)

หากคุณต้องการอ่านเพิ่มเติมเกี่ยวกับสาเหตุ:

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


3
มันไม่ได้ช่วยเหลือเกี่ยวกับปัญหาของ OP: "ไม่สามารถเข้ารหัสตัวอักษร U '\ u2019" u'\u2019เป็น Unicode อยู่แล้ว
jfs

6

อย่าฮาร์ดโค้ดการเข้ารหัสอักขระของสภาพแวดล้อมภายในสคริปต์ของคุณ พิมพ์ข้อความ Unicode โดยตรงแทน:

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

หากเอาต์พุตของคุณถูกเปลี่ยนเส้นทางไปยังไฟล์ (หรือไปป์) คุณสามารถใช้PYTHONIOENCODINGenvvar เพื่อระบุการเข้ารหัสอักขระ:

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

มิฉะนั้นpython your_script.pyควรจะทำงานที่เป็นอยู่ - การตั้งค่าสถานที่ของคุณจะใช้ในการเข้ารหัสข้อความ (ใน POSIX ตรวจสอบ: LC_ALL, LC_CTYPE, LANGenvvars - ชุดLANGกับ UTF-8 สถานที่เกิดเหตุถ้าจำเป็น)

หากต้องการพิมพ์ Unicode บน Windows, ดูคำตอบที่แสดงให้เห็นถึงวิธีการพิมพ์ Unicode กับ Windows คอนโซลไปยังไฟล์หรือใช้ IDLE


1

โพสต์ยอดเยี่ยม: http://www.carlosble.com/2010/12/understand-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

คุณสามารถใช้บางอย่างในแบบฟอร์ม

s.decode('utf-8')

ซึ่งจะแปลงการทดสอบการเข้ารหัส UTF-8 เป็นสตริง Python Unicode แต่ขั้นตอนที่แน่นอนในการใช้งานขึ้นอยู่กับว่าวิธีที่คุณโหลดและแยกไฟล์ XML เช่นถ้าคุณไม่เคยเข้าถึงสตริง XML โดยตรงคุณอาจมีการใช้วัตถุถอดรหัสจากโมดูลcodecs


มีการเข้ารหัส UTF-8 แล้วข้อผิดพลาดมีไว้โดยเฉพาะ: myStrings = deque (ข้อความ [u'Dorf และ Svoboda สร้างขึ้นบน str ... และสาขาย่อยวิศวกรรมคอมพิวเตอร์ ']) สตริงอยู่ใน UTF-8 เป็น คุณสามารถเห็นได้ แต่มันบ้าคลั่งเกี่ยวกับ '\ u2019' ภายใน
Alex B

โอเคฉันคิดว่าคุณกำลังมีปัญหาอื่น
David Z

7
@ Alex B: ไม่สตริงคือ Unicode ไม่ใช่ Utf-8 ในการเข้ารหัสเป็น Utf-8 ให้ใช้'...'.encode('utf-8')
sth

0

ฉันเขียนสิ่งต่อไปนี้เพื่อแก้ไขอัญประกาศที่ไม่ใช่ ascii และบังคับให้แปลงเป็นสิ่งที่ใช้งานได้

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

หากคุณต้องการพิมพ์การแสดงสตริงโดยประมาณบนหน้าจอแทนที่จะละเว้นอักขระที่พิมพ์ไม่ได้เหล่านั้นโปรดลองใช้unidecodeแพ็คเกจที่นี่:

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

คำอธิบายอยู่ที่นี่:

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

สิ่งนี้ดีกว่าการใช้u.encode('ascii', 'ignore')สำหรับสตริงที่กำหนดuและช่วยให้คุณไม่ต้องปวดหัวโดยไม่จำเป็นหากความแม่นยำของอักขระไม่ใช่สิ่งที่คุณเป็นหลังจากนั้น แต่ก็ยังต้องการให้มนุษย์อ่านได้

วีรวรรณ



-1

Python 3.5, 2018

หากคุณไม่ได้รู้ว่าสิ่งที่เข้ารหัส แต่ parser Unicode จะมีปัญหาคุณสามารถเปิดไฟล์ในและในแถบด้านบนเลือกNotepad++ Encoding->Convert to ANSIจากนั้นคุณสามารถเขียน python ของคุณแบบนี้

with open('filepath', 'r', encoding='ANSI') as file:
    for word in file.read().split():
        print(word)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.