Lỗi mã hóa Python Unicode


104

Tôi đang đọc và phân tích cú pháp tệp XML của Amazon và trong khi tệp XML hiển thị dấu ', khi tôi cố gắng in nó, tôi gặp lỗi sau:

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

Theo những gì tôi đã đọc trực tuyến cho đến nay, lỗi là do tệp XML ở dạng UTF-8, nhưng Python muốn xử lý nó như một ký tự được mã hóa ASCII. Có cách nào đơn giản để làm cho lỗi biến mất và để chương trình của tôi in XML khi nó đọc không?


Tôi chỉ đến SO để đăng câu hỏi này. Có cách nào dễ dàng để khử trùng một chuỗi unicode()không?
Nick Heiner

Vui lòng kiểm tra câu trả lời này cho một câu hỏi liên quan: “Python UnicodeDecodeError - Tôi có đang hiểu sai về mã hóa không?”
tzot

Câu trả lời:


193

Có thể, vấn đề của bạn là bạn đã phân tích cú pháp nó không sao, và bây giờ bạn đang cố in nội dung của XML và bạn không thể vì có một số ký tự Unicode ngoại lai. Trước tiên, hãy thử mã hóa chuỗi unicode của bạn dưới dạng ascii:

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

phần 'bỏ qua' sẽ yêu cầu nó bỏ qua các ký tự đó. Từ tài liệu về trăn:

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

Bạn có thể muốn đọc bài viết này: http://www.joelonsoftware.com/articles/Unicode.html , mà tôi thấy rất hữu ích như một hướng dẫn cơ bản về những gì đang xảy ra. Sau khi đọc xong, bạn sẽ không còn cảm thấy như mình chỉ đang đoán những lệnh sẽ sử dụng (hoặc ít nhất là điều đó đã xảy ra với tôi).


1
Tôi đang cố gắng làm cho chuỗi sau an toàn: 'foo "bar bar" df' (lưu ý dấu ngoặc kép), nhưng tôi vẫn gặp lỗi ở trên.
Nick Heiner

@Rosarch: Không thành công như thế nào? cùng một lỗi? Và bạn đã sử dụng quy tắc xử lý lỗi nào?
Scott Stafford

@Rosarch, vấn đề của bạn có lẽ là sớm hơn. Hãy thử mã này: # - - coding: latin-1 - - u = u 'foo “bar bar” df' print u.encode ('ascii', 'ignore') Đối với bạn, nó có thể đang chuyển đổi chuỗi của bạn THÀNH unicode đã cho mã hóa bạn đã chỉ định cho tập lệnh python đã gây ra lỗi.
Scott Stafford

Tôi đã tiếp tục và đặt vấn đề của mình thành câu hỏi của riêng nó: stackoverflow.com/questions/3224427/…
Nick Heiner

1
.encode('ascii', 'ignore')mất dữ liệu không cần thiết ngay cả khi môi trường OP của có thể hỗ trợ các ký tự không ascii (hầu hết trường hợp)
JFS

16

Một giải pháp tốt hơn:

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)

Nếu bạn muốn đọc thêm về lý do:

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


3
Nó không giải quyết được vấn đề của OP: "không thể mã hóa ký tự u '\ u2019'" . u'\u2019đã là Unicode.
jfs

6

Đừng hardcode mã hóa ký tự của môi trường bên trong script của bạn; in trực tiếp văn bản Unicode thay thế:

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

Nếu đầu ra của bạn được chuyển hướng đến một tệp (hoặc một đường ống); bạn có thể sử dụng PYTHONIOENCODINGenvvar, để chỉ định mã hóa ký tự:

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

Nếu không, python your_script.pynên hoạt động như là - cài đặt ngôn ngữ của bạn được sử dụng để mã hóa văn bản (trên POSIX kiểm tra: LC_ALL, LC_CTYPE, LANGenvvars - bộ LANGđến một miền địa phương utf-8 nếu cần).

Để in Unicode trên Windows, hãy xem câu trả lời này cho biết cách in Unicode vào bảng điều khiển Windows, vào tệp hoặc sử dụng IDLE .


1

Bài đăng xuất sắc: http://www.carlosble.com/2010/12/und hieu-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

Bạn có thể sử dụng một cái gì đó có dạng

s.decode('utf-8')

sẽ chuyển đổi bytestring mã hóa UTF-8 thành một chuỗi Python Unicode. Nhưng quy trình chính xác để sử dụng phụ thuộc vào chính xác cách bạn tải và phân tích cú pháp tệp XML, ví dụ: nếu bạn không bao giờ truy cập trực tiếp vào chuỗi XML, bạn có thể phải sử dụng một đối tượng bộ giải mã từ codecsmô-đun .


Nó đã được mã hóa bằng UTF-8. Lỗi cụ thể là: myStrings = deque ([u'Dorf và Svoboda \ u2019s text xây dựng trên str ... và Computer Engineering \ u2019s subdisciplines. ']) Chuỗi trong UTF-8 là bạn có thể nhìn thấy, nhưng nó nổi giận về nội '\ u2019'
Alex B

Ồ, được rồi, tôi nghĩ bạn đang gặp một vấn đề khác.
David Z,

7
@Alex B: Không, chuỗi là Unicode, không phải Utf-8. Để mã hóa nó thành Utf-8, hãy sử dụng'...'.encode('utf-8')
sth

0

Tôi đã viết phần sau để sửa lỗi các dấu ngoặc kép không phải ascii phiền toái và buộc chuyển đổi thành một thứ có thể sử dụng được.

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

Nếu bạn cần in biểu diễn gần đúng của chuỗi ra màn hình, thay vì bỏ qua các ký tự không in được đó, vui lòng thử unidecodegói tại đây:

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

Lời giải thích được tìm thấy ở đây:

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

Điều này tốt hơn là sử dụng u.encode('ascii', 'ignore')cho một chuỗi nhất định uvà có thể giúp bạn khỏi đau đầu không cần thiết nếu độ chính xác của ký tự không như bạn mong muốn, nhưng vẫn muốn con người có thể đọc được.

Wirawan


-1

Hãy thử thêm dòng sau vào đầu tập lệnh python của bạn.

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

-1

Python 3.5, 2018

Nếu bạn không biết mã hóa gì nhưng trình phân tích cú pháp unicode đang gặp sự cố, bạn có thể mở tệp trong Notepad++và chọn ở thanh trên cùng Encoding->Convert to ANSI. Sau đó, bạn có thể viết python của bạn như thế này

with open('filepath', 'r', encoding='ANSI') as file:
    for word in file.read().split():
        print(word)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.