2010-07-11 42 views
86

tôi đang đọc và phân tích một tập tin XML Amazon và trong khi các tập tin XML cho thấy một ', khi tôi cố gắng in nó tôi nhận được lỗi sau:Python Unicode Encode Lỗi

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

Từ những gì tôi đã đọc trực tuyến cho đến nay, lỗi xuất phát từ thực tế là tệp XML nằm trong UTF-8, nhưng Python muốn xử lý nó như một ký tự mã hóa ASCII. Có một cách đơn giản để làm cho các lỗi biến mất và có chương trình của tôi in XML khi nó đọc?

+0

Tôi vừa đến SO để đăng câu hỏi này. Có một cách dễ dàng để khử trùng một chuỗi cho 'unicode()'? –

+0

Vui lòng kiểm tra [this] (http://stackoverflow.com/questions/3224427/python-sanitize-a-string-for-unicode/3224890#3224890) trả lời cho một câu hỏi liên quan: “Python UnicodeDecodeError - Tôi có phải mã hóa sự hiểu lầm không ? ” – tzot

Trả lời

163

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

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

phần 'bỏ qua' sẽ cho biết chỉ bỏ qua các ký tự đó. Từ các tài liệu 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;' 

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, bạn sẽ ngừng cảm thấy như bạn chỉ đoán những gì lệnh để sử dụng (hoặc ít nhất là đã xảy ra với tôi).

+1

Tôi đang cố gắng để làm cho chuỗi sau đây an toàn: 'foo' bar bar 'df' (lưu ý các dấu ngoặc kép), nhưng những điều trên vẫn không thành công đối với tôi. –

+0

@Rosarch: Không có cách nào? cùng một lỗi? Và bạn đã sử dụng quy tắc xử lý lỗi nào? –

+0

@Rosarch, vấn đề của bạn có thể sớm hơn. Hãy thử mã này: # - * - mã hóa: latin-1 - * - u = u 'foo ‘thanh thanh’ df' in u.encode ('ascii', 'bỏ ​​qua') Đối với bạn, nó có lẽ đã chuyển đổi chuỗi unicode INTO của bạn bằng mã hóa mà bạn đã chỉ định cho tập lệnh python đã ném lỗi. –

0

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

s.decode('utf-8') 

mà sẽ chuyển đổi một UTF-8 mã hóa bytestring thành một chuỗi Python Unicode. Nhưng quy trình sử dụng chính xác tùy thuộc vào 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 chuỗi XML trực tiếp, bạn có thể phải sử dụng một đối tượng bộ giải mã từ codecs module.

+0

Lỗi này được mã hóa theo UTF-8 Lỗi này cụ thể là: myStrings = deque (văn bản [u'Dorf và Svoboda \ u2019s xây dựng trên các phân ngành ... và Kỹ thuật Máy tính \ '.]] chuỗi là UTF-8 như bạn có thể thấy, nhưng nó phát điên về nội bộ '\ u2019' –

+0

Ồ, OK, tôi nghĩ bạn đang gặp sự cố khác. –

+7

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

13

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 tìm hiểu thêm về lý do tại sao:

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

+3

Nó không giúp với vấn đề của OP: * "không thể mã hóa ký tự u '\ u2019'" *. 'u '\ u2019' đã là Unicode. – jfs

3

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

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 tệp (hoặc ống); bạn có thể sử dụng PYTHONIOENCODING envvar, để xác định mã hóa ký tự:

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

Nếu không, python your_script.py nê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 séc POSIX: LC_ALL, LC_CTYPE, LANG envvars - đặt LANG thành ngôn ngữ utf-8 nếu cần).

To print Unicode on Windows, see this answer that shows how to print Unicode to Windows console, to a file, or using IDLE.

0

Tôi đã viết phần sau để sửa các dấu ngoặc kép không ascii phiền toái và chuyển đổi lực lượng 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

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

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

Cú pháp chính xác là: '# - * - mã hóa: utf-8 - * -' – azuax

1

bài xuất sắc: 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

Nếu bạn cần in một đại diện xấp xỉ chuỗi ra màn hình, chứ không phải bỏ qua những ký tự không in, hãy thử unidecode gói ở đây:

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

Giải thích được tìm thấy tại đây:

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

này là tốt hơn so với sử dụng các u.encode('ascii', 'ignore') cho một chuỗi cho trước u, và có thể giúp bạn tiết kiệm từ đau đầu không cần thiết nếu nhân vật chính xác không phải là những gì bạn đang sau, nhưng vẫn muốn có khả năng đọc của con người.

Wirawan

Các vấn đề liên quan