UnicodeEncodeError: 'ascii' codec không thể mã hóa ký tự u '\ xa0' ở vị trí 20: thứ tự không nằm trong phạm vi (128)


1297

Tôi đang gặp vấn đề với việc xử lý các ký tự unicode từ văn bản được tải từ các trang web khác nhau (trên các trang web khác nhau). Tôi đang sử dụng BeautifulSoup.

Vấn đề là lỗi không phải lúc nào cũng có thể lặp lại; đôi khi nó hoạt động với một số trang, và đôi khi, nó bị chặn bằng cách ném a UnicodeEncodeError. Tôi đã thử mọi thứ tôi có thể nghĩ ra, nhưng tôi chưa tìm thấy bất cứ thứ gì hoạt động ổn định mà không gây ra một số lỗi liên quan đến Unicode.

Một trong những phần của mã gây ra sự cố được hiển thị bên dưới:

agent_telno = agent.find('div', 'agent_contact_number')
agent_telno = '' if agent_telno is None else agent_telno.contents[0]
p.agent_info = str(agent_contact + ' ' + agent_telno).strip()

Dưới đây là dấu vết ngăn xếp được tạo trên chuỗi MỘT SỐ khi đoạn mã trên được chạy:

Traceback (most recent call last):
  File "foobar.py", line 792, in <module>
    p.agent_info = str(agent_contact + ' ' + agent_telno).strip()
UnicodeEncodeError: 'ascii' codec can't encode character u'\xa0' in position 20: ordinal not in range(128)

Tôi nghi ngờ rằng điều này là do một số trang (hoặc cụ thể hơn, các trang từ một số trang web) có thể được mã hóa, trong khi các trang khác có thể không được mã hóa. Tất cả các trang web đều có trụ sở tại Vương quốc Anh và cung cấp dữ liệu dành cho tiêu dùng ở Vương quốc Anh - vì vậy không có vấn đề nào liên quan đến nội địa hóa hoặc xử lý văn bản được viết bằng bất cứ thứ gì ngoài tiếng Anh.

Có ai có bất kỳ ý tưởng nào về cách giải quyết vấn đề này để tôi có thể khắc phục sự cố này không?


1
Nếu bạn nhận được các lỗi này như một người sử dụng chứ không phải là một nhà phát triển, kiểm tra serverfault.com/questions/54591/...askubuntu.com/questions/599808/...
Đó Brazil Guy

Tôi sẽ thêm điểm này không sử dụng onlinegdb.com/online_python_interpreter cho nội dung này. Đã sử dụng trình thông dịch đó để dùng thử và nó không được cấu hình đúng cho Unicode! Luôn luôn được in ở định dạng 'B' \ nnn '' ... khi tất cả những gì tôi muốn là một máy chém! Đã thử trên máy ảo và nó hoạt động ngay lập tức như mong đợi bằng cách sử dụng chr ()
JGFMK

4
Hãy thử điều này import os; import locale; os.environ["PYTHONIOENCODING"] = "utf-8"; myLocale=locale.setlocale(category=locale.LC_ALL, locale="en_GB.UTF-8"); ... print(myText.encode('utf-8', errors='ignore')).
hhh

@hhh Tôi đã chạy đoạn trích Tên của bạnError: tên 'myText' không được xác định
KHAN irfan

9
Hãy thử đặt PYTHONIOENCODING trong trình bao, trước khi thực hiện tập lệnh của bạn:$ export PYTHONIOENCODING=utf8
Noam Manos

Câu trả lời:


1363

Bạn cần phải đọc Python Unicode HOWTO . Lỗi này là ví dụ đầu tiên .

Về cơ bản, ngừng sử dụng strđể chuyển đổi từ unicode sang văn bản / byte được mã hóa.

Thay vào đó, sử dụng đúng cách .encode()để mã hóa chuỗi:

p.agent_info = u' '.join((agent_contact, agent_telno)).encode('utf-8').strip()

hoặc làm việc hoàn toàn trong unicode.


23
đã đồng ý! Một quy tắc tốt mà tôi được dạy là sử dụng ý tưởng "unicode sandwich". Tập lệnh của bạn chấp nhận byte từ thế giới bên ngoài, nhưng tất cả quá trình xử lý nên được thực hiện trong unicode. Chỉ khi bạn sẵn sàng xuất dữ liệu của mình thì dữ liệu mới được đưa trở lại thành byte!
Andbdrew

256
Trong trường hợp người khác bị nhầm lẫn bởi điều này, tôi đã tìm thấy một điều kỳ lạ: thiết bị đầu cuối của tôi sử dụng utf-8 và khi tôi sử dụng printchuỗi utf-8, nó hoạt động rất tốt. Tuy nhiên khi tôi chuyển các chương trình của mình ra một tệp, nó sẽ ném a UnicodeEncodeError. Trong thực tế, khi đầu ra được chuyển hướng (đến một tệp hoặc một đường ống), tôi thấy đó sys.stdout.encodingNone! Xử .encode('utf-8')lý vấn đề.
drevicko

93
@drevicko: PYTHONIOENCODING=utf-8thay vào đó, hãy sử dụng các chuỗi Unicode và để môi trường đặt mã hóa dự kiến.
jfs

1
@steinar: không có gì là hợp lệ trong mọi trường hợp. Nói chung, người dùng không nên quan tâm rằng bạn sử dụng Python để triển khai tiện ích của mình (giao diện không nên thay đổi nếu bạn quyết định thực hiện lại bằng ngôn ngữ khác vì bất kỳ lý do gì) và do đó bạn không nên mong đợi người dùng đó biết về python- đặc sứ cụ thể. Đó là giao diện người dùng xấu để buộc người dùng chỉ định mã hóa ký tự; nhúng mã hóa ký tự trong định dạng báo cáo nếu cần thiết. Lưu ý: không có mã hóa mã hóa cứng nào có thể là "mặc định hợp lý" trong trường hợp chung.
JFS

13
Đây là lời khuyên tồi tệ và khó hiểu. Lý do mọi người sử dụng str là vì đối tượng KHÔNG phải là một chuỗi, vì vậy không có .encode()phương thức nào để gọi.
Cerin

434

Đây là một điểm đau trăn unicode cổ điển! Hãy xem xét những điều sau đây:

a = u'bats\u00E0'
print a
 => batsà

Tất cả đều tốt cho đến nay, nhưng nếu chúng ta gọi str (a), hãy xem điều gì xảy ra:

str(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe0' in position 4: ordinal not in range(128)

Oh nhúng, điều đó sẽ không làm bất cứ ai tốt! Để sửa lỗi, mã hóa các byte rõ ràng bằng .encode và báo cho python biết nên sử dụng codec nào:

a.encode('utf-8')
 => 'bats\xc3\xa0'
print a.encode('utf-8')
 => batsà

Voil \ u00E0!

Vấn đề là khi bạn gọi str (), python sử dụng mã hóa ký tự mặc định để thử và mã hóa các byte bạn đã cung cấp, trong trường hợp của bạn đôi khi là biểu diễn của các ký tự unicode. Để khắc phục sự cố, bạn phải cho python biết cách xử lý chuỗi bạn cung cấp bằng cách sử dụng .encode ('anything_unicode'). Hầu hết thời gian, bạn sẽ ổn khi sử dụng utf-8.

Để có một giải trình xuất sắc về chủ đề này, hãy xem bài nói về PyCon của Ned Batchelder tại đây: http://nedbatchelder.com/text/unipain.html


85
Lưu ý cá nhân: Khi cố gắng gõ ".encode" đừng vô tình gõ ".unicode" thì hãy tự hỏi tại sao không có gì hoạt động.
Bỏ qua Huffman

9
Lời khuyên tốt. Nhưng bạn sẽ làm gì thay vào đó khi bạn đang sử dụng str (x) để in các đối tượng có thể có hoặc không phải là chuỗi? str (x) hoạt động nếu x là một số, thời gian ngày, boolean hoặc chuỗi bình thường. Đột nhiên nếu một unicode nó ngừng hoạt động. Có cách nào để có được hành vi tương tự hay bây giờ chúng ta cần thêm kiểm tra IF để kiểm tra xem đối tượng có phải là chuỗi để sử dụng .encode và str () không?
Dirk R

Câu hỏi tương tự có thể được hỏi với Nonegiá trị.
Vadorequest

210

Tôi đã tìm thấy công việc tao nhã xung quanh để xóa các ký hiệu và tiếp tục giữ chuỗi dưới dạng chuỗi sau:

yourstring = yourstring.encode('ascii', 'ignore').decode('ascii')

Điều quan trọng cần lưu ý là việc sử dụng tùy chọn bỏ qua là nguy hiểm vì nó âm thầm loại bỏ mọi hỗ trợ unicode (và quốc tế hóa) khỏi mã sử dụng nó, như đã thấy ở đây (chuyển đổi unicode):

>>> u'City: Malmö'.encode('ascii', 'ignore').decode('ascii')
'City: Malm'

17
Bạn đã làm cho ngày của tôi! Đối với utf-8, điều đó là đủ để làm:yourstring = yourstring.encode('utf-8', 'ignore').decode('utf-8')
luca76

Đối với tôi điều này đã làm việc nhưng trường hợp của tôi thì khác, tôi đã lưu tên tệp và có "/" trong tên và đường dẫn không tồn tại nên tôi phải sử dụng .replace ("/", "") và do đó đã lưu kịch bản của tôi. trong khi bỏ qua ascii cũng hoạt động cho trường hợp 'utf-8'.
Akash Kandpal

1
@ harrypotter0 để nối các đường dẫn tệp được sử dụng một cách chính xác os.path.join(), đó là một thói quen rất tốt khi bạn bắt đầu thực hiện lập trình đa nền tảng. :)
login_not_fails

152

tôi đã thử tất cả mọi thứ nhưng không có ích gì, sau khi loay hoay xung quanh tôi đã tìm ra những điều sau đây và nó đã giúp ích. python 2.7 đang được sử dụng.

# encoding=utf8
import sys
reload(sys)
sys.setdefaultencoding('utf8')

7
Đừng làm điều này. stackoverflow.com/questions/3828723/ , mặc dù khi bạn có câu trả lời như thế này stackoverflow.com/a/31137935/2141635 gần đầu kết quả khi bạn tìm kiếm lỗi tôi có thể thấy tại sao nó có vẻ là một ý tưởng hay.
Padraic Cickyham

21
Tôi đã thử hầu hết tất cả các đề xuất trong chủ đề này và thực sự không có gợi ý nào cho tôi. Cuối cùng tôi đã thử cái này. Và nó thực sự là thứ duy nhất làm việc đơn giản và tốt. Nếu ai đó nói "Đừng làm điều này, thì hãy đi kèm với một Giải pháp đơn giản. Nếu không hãy sử dụng giải pháp này. Bởi vì đó là một bản sao hoạt động tốt và giải pháp trong quá khứ.
Richard de Ree

4
Làm thế nào điều này có thể được thực hiện trong python3? Sẽ rất vui khi biết.
Kanerva Peter

3
Sau rất nhiều thất vọng, điều này làm việc. Cảm ơn nhiều.
Avraham Zhurba

4
Tôi chỉ cần thêm một if sys.version_info.major < 3:
hợp đồng

87

Một vấn đề tinh tế khiến thậm chí in thất bại là các biến môi trường của bạn được đặt sai, ví dụ. ở đây LC_ALL được đặt thành "C". Trong Debian họ không khuyến khích cài đặt nó: Debian wiki trên Locale

$ echo $LANG
en_US.utf8
$ echo $LC_ALL 
C
$ python -c "print (u'voil\u00e0')"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe0' in position 4: ordinal not in range(128)
$ export LC_ALL='en_US.utf8'
$ python -c "print (u'voil\u00e0')"
voilà
$ unset LC_ALL
$ python -c "print (u'voil\u00e0')"
voilà

Có cùng một vấn đề, rất tệ, tôi đã không kiểm tra nó trước khi báo cáo . Cảm ơn rất nhiều. Nhân tiện, bạn có thể thay thế hai lệnh đầu tiên bằng env|grep -E '(LC|LANG)'.
Dmitry Verhoturov

Chỉ cần hai xu của tôi về vấn đề mã hóa sai. Tôi thường xuyên sử dụng mctrong "chế độ subshell" ( Ctrl-O) và tôi cũng quên rằng tôi đã thêm bí danh sau vào bash : alias mc="LANG=en_EN.UTF-8 mc". Vì vậy, khi tôi cố gắng chạy các kịch bản viết kém dựa vào ru_RU.UTF-8nội bộ, họ sẽ chết. Đã thử rất nhiều thứ từ chủ đề này trước khi tôi phát hiện ra vấn đề thực sự. :)
login_not_fails

BẠN THẬT TUYỆT VỜI. Trong GSUTIL, rsync của tôi đã thất bại vì chính xác vấn đề này. Đã sửa lỗi LC_ALL và mọi thứ hoạt động tốt như rượu vang. <3 CẢM ƠN BẠN <3
DSignr

27

Đối với tôi, những gì đã làm việc là:

BeautifulSoup(html_text,from_encoding="utf-8")

Hy vọng điều này sẽ giúp được ai đó.


25

Tôi thực sự đã thấy rằng trong hầu hết các trường hợp của mình, việc loại bỏ những ký tự đó đơn giản hơn nhiều:

s = mystring.decode('ascii', 'ignore')

26
"Hoàn hảo" thường không phải là những gì nó thực hiện. Nó vứt bỏ những thứ mà bạn nên tìm ra cách giải quyết đúng đắn.
tripleee

7
chỉ cần loại bỏ các ký tự "đó" (không phải tiếng Anh) không phải là giải pháp vì python phải hỗ trợ tất cả các ngôn ngữ bạn không nghĩ sao?
alemol

8
Bị hạ bệ. Đây không phải là giải pháp chính xác cả. Tìm hiểu cách làm việc với Unicode: joelonsoftware.com/articles/Unicode.html
Andrew Ferrier

4
Hãy nhìn xem, cách khôn ngoan nhất để trình bày câu trả lời cụ thể này là theo cách này: nhận ra rằng ascii dành một đặc quyền nhất định cho một số ngôn ngữ và người dùng nhất định - đây là lối thoát có thể bị khai thác cho những người dùng có thể đang hack một lời nguyền , tập lệnh cùng nhau có khả năng cho công việc sơ bộ trước khi hỗ trợ unicode đầy đủ được triển khai.
lol

5
Nếu tôi đang viết một tập lệnh chỉ cần in văn bản tiếng Anh để xuất bản trong ứng dụng nội bộ của công ty, tôi chỉ muốn vấn đề biến mất. Dù làm việc gì.
kagronick

25

Vấn đề là bạn đang cố in một ký tự unicode, nhưng thiết bị đầu cuối của bạn không hỗ trợ nó.

Bạn có thể thử cài đặt language-pack-engói để sửa lỗi đó:

sudo apt-get install language-pack-en

cung cấp cập nhật dữ liệu dịch tiếng Anh cho tất cả các gói được hỗ trợ (bao gồm cả Python). Cài đặt gói ngôn ngữ khác nhau nếu cần thiết (tùy thuộc vào ký tự bạn đang cố in).

Trên một số bản phân phối Linux, cần phải đảm bảo rằng các ngôn ngữ tiếng Anh mặc định được thiết lập đúng (vì vậy các ký tự unicode có thể được xử lý bằng shell / terminal). Đôi khi dễ cài đặt nó hơn là cấu hình thủ công.

Sau đó, khi viết mã, hãy chắc chắn rằng bạn sử dụng mã hóa đúng trong mã của mình.

Ví dụ:

open(foo, encoding='utf-8')

Nếu bạn vẫn gặp sự cố, hãy kiểm tra kỹ cấu hình hệ thống của bạn, chẳng hạn như:

  • Tệp ngôn ngữ của bạn ( /etc/default/locale), cần có, vd

    LANG="en_US.UTF-8"
    LC_ALL="en_US.UTF-8"

    hoặc là:

    LC_ALL=C.UTF-8
    LANG=C.UTF-8
  • Giá trị của LANG/ LC_CTYPEtrong vỏ.

  • Kiểm tra miền địa phương mà vỏ của bạn hỗ trợ bằng cách:

    locale -a | grep "UTF-8"

Trình bày vấn đề và giải pháp trong VM mới.

  1. Khởi tạo và cung cấp VM (ví dụ: sử dụng vagrant):

    vagrant init ubuntu/trusty64; vagrant up; vagrant ssh

    Xem: hộp Ubuntu có sẵn . .

  2. In các ký tự unicode (như dấu hiệu thương mại như ):

    $ python -c 'print(u"\u2122");'
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
    UnicodeEncodeError: 'ascii' codec can't encode character u'\u2122' in position 0: ordinal not in range(128)
  3. Hiện đang cài đặt language-pack-en:

    $ sudo apt-get -y install language-pack-en
    The following extra packages will be installed:
      language-pack-en-base
    Generating locales...
      en_GB.UTF-8... /usr/sbin/locale-gen: done
    Generation complete.
  4. Bây giờ vấn đề cần được giải quyết:

    $ python -c 'print(u"\u2122");'
    
  5. Nếu không, hãy thử lệnh sau:

    $ LC_ALL=C.UTF-8 python -c 'print(u"\u2122");'
    

1
Điều gì đã language-pack-enxảy ra với Python hoặc câu hỏi này? AFAIK, nó có thể cung cấp bản dịch ngôn ngữ cho tin nhắn nhưng không liên quan gì đến mã hóa
Alastair McCormack

2
Trên một số bản phân phối Linux, cần phải đảm bảo rằng các ngôn ngữ tiếng Anh mặc định được thiết lập đúng, đặc biệt là khi chạy tập lệnh Python trên Terminal. Nó làm việc cho tôi tại một thời điểm. Xem: mã hóa ký tự
kenorb

À, được rồi Bạn có nghĩa là nếu bạn muốn sử dụng một ngôn ngữ không phải tiếng Anh? Tôi đoán người dùng cũng sẽ phải chỉnh sửa /etc/locale.genđể đảm bảo ngôn ngữ của họ được xây dựng trước khi sử dụng?
Alastair McCormack

1
@AlastairMcCormack Đã nhận xét LANGtừ /etc/default/locale(như không /etc/locale.gentồn tại) và chạy locale-gen, nhưng nó không giúp được gì. Tôi không chắc language-pack-enchính xác những gì nó làm, vì tôi đã không tìm thấy nhiều tài liệu và liệt kê nội dung của nó không giúp được gì nhiều.
kenorb

1
không có khả năng là không có địa điểm utf-8 trên hệ thống máy tính để bàn, nghĩa là bạn không cần phải cài đặt bất cứ thứ gì, chỉ cần cấu hình LANG/ LC_CTYPE/ LC_ALLthay vào đó (ví dụ LANG=C.UTF-8:).
JFS

19

Trong vỏ bọc:

  1. Tìm ngôn ngữ UTF-8 được hỗ trợ bằng lệnh sau:

    locale -a | grep "UTF-8"
  2. Xuất nó, trước khi chạy tập lệnh, ví dụ:

    export LC_ALL=$(locale -a | grep UTF-8)

    hoặc thủ công như:

    export LC_ALL=C.UTF-8
  3. Kiểm tra nó bằng cách in ký tự đặc biệt, ví dụ :

    python -c 'print(u"\u2122");'

Trên đã thử nghiệm trong Ubuntu.


Có, đây là câu trả lời ngắn tốt nhất, chúng tôi không thể sửa đổi mã nguồn để sử dụng .encode
Luat Nguyen - Neo.Mxn0

16

Thêm dòng bên dưới vào đầu tập lệnh của bạn (hoặc dưới dạng dòng thứ hai):

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

Đó là định nghĩa của mã hóa mã nguồn python. Thêm thông tin trong PEP 263 .


2
Điều này không giải quyết được vấn đề khi văn bản được xử lý được tải từ tệp bên ngoài chứa mã hóa utf-8. Điều này chỉ giúp cho các chữ được viết trong chính tập lệnh python đã cho và chỉ là đầu mối cho trình thông dịch python, nhưng không có tác động đến việc xử lý văn bản.
Mikaelblomkvistsson

16

Đây là một bản tóm tắt của một số câu trả lời được gọi là "cop out". Có những tình huống chỉ cần vứt bỏ các ký tự / chuỗi rắc rối là một giải pháp tốt, bất chấp các cuộc biểu tình lên tiếng ở đây.

def safeStr(obj):
    try: return str(obj)
    except UnicodeEncodeError:
        return obj.encode('ascii', 'ignore').decode('ascii')
    except: return ""

Kiểm tra nó:

if __name__ == '__main__': 
    print safeStr( 1 ) 
    print safeStr( "test" ) 
    print u'98\xb0'
    print safeStr( u'98\xb0' )

Các kết quả:

1
test
98°
98

Gợi ý: bạn có thể muốn đặt tên cho chức năng này để toAsciithay thế? Đó là vấn đề ưu tiên.

Điều này được viết cho Python 2. Đối với Python 3, tôi tin rằng bạn sẽ muốn sử dụng bytes(obj,"ascii")hơn là str(obj). Tôi đã không kiểm tra điều này chưa, nhưng một lúc nào đó tôi sẽ xem lại câu trả lời.


8

Tôi luôn đặt mã dưới đây trong hai dòng đầu tiên của tệp python:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

6

Chức năng trợ giúp đơn giản được tìm thấy ở đây .

def safe_unicode(obj, *args):
    """ return the unicode representation of obj """
    try:
        return unicode(obj, *args)
    except UnicodeDecodeError:
        # obj is byte string
        ascii_text = str(obj).encode('string_escape')
        return unicode(ascii_text)

def safe_str(obj):
    """ return the byte string representation of obj """
    try:
        return str(obj)
    except UnicodeEncodeError:
        # obj is unicode
        return unicode(obj).encode('unicode_escape')

Để có được bytestring thoát (để chuyển đổi chuỗi Unicode tùy ý thành byte bằng mã hóa ascii), bạn có thể sử dụng backslashreplacetrình xử lý lỗi : u'\xa0'.encode('ascii', 'backslashreplace'). Mặc dù bạn nên tránh đại diện như vậy và cấu hình môi trường của bạn để chấp nhận các ký tự không phải ascii thay vào đó - đó là năm 2016!
JFS

Chúc mừng năm mới @JFSebastian. Tôi đã nản lòng với vấn đề Python-Unicode và cuối cùng đã có giải pháp này đang hoạt động. Tôi đã không biết về điều này. Dù sao cũng cảm ơn vì tiền boa.
Parag Tyagi



3

Tôi chỉ sử dụng như sau:

import unicodedata
message = unicodedata.normalize("NFKD", message)

Kiểm tra những gì tài liệu nói về nó:

unicodingata.n normalize (form, unistr) Trả về dạng biểu mẫu bình thường cho chuỗi Unicode unistr. Các giá trị hợp lệ cho biểu mẫu là 'NFC', 'NFKC', 'NFD' và 'NFKD'.

Tiêu chuẩn Unicode định nghĩa các dạng chuẩn hóa khác nhau của chuỗi Unicode, dựa trên định nghĩa về tương đương chính tắc và tương đương tương thích. Trong Unicode, một số ký tự có thể được thể hiện theo nhiều cách khác nhau. Ví dụ, ký tự U + 00C7 (LATIN VỐN THƯỞNG C VỚI CEDILLA) cũng có thể được biểu thị dưới dạng chuỗi U + 0043 (LATIN VỐN THƯỞNG C) U + 0327 (COMBINING CEDILLA).

Đối với mỗi ký tự, có hai dạng bình thường: dạng bình thường C và dạng bình thường D. Dạng bình thường D (NFD) còn được gọi là phân rã chính tắc, và chuyển từng ký tự thành dạng phân tách. Dạng C (NFC) thông thường trước tiên áp dụng phân tách chính tắc, sau đó kết hợp lại các ký tự được kết hợp lại.

Ngoài hai hình thức này, có hai hình thức bình thường bổ sung dựa trên sự tương đương. Trong Unicode, một số ký tự được hỗ trợ mà thông thường sẽ được hợp nhất với các ký tự khác. Ví dụ, U + 2160 (ROMAN SỐ MỘT) thực sự giống với U + 0049 (LATIN VỐN BÀI I). Tuy nhiên, nó được hỗ trợ bằng Unicode để tương thích với các bộ ký tự hiện có (ví dụ: gb2312).

Dạng KD bình thường (NFKD) sẽ áp dụng phân tách tương thích, tức là thay thế tất cả các ký tự tương thích bằng các tương đương của chúng. Dạng bình thường KC (NFKC) trước tiên áp dụng phân tách tương thích, tiếp theo là thành phần chính tắc.

Ngay cả khi hai chuỗi unicode được chuẩn hóa và trông giống nhau đối với người đọc, nếu một chuỗi có các ký tự kết hợp và chuỗi kia không, chúng có thể không so sánh bằng nhau.

Giải quyết nó cho tôi. Đơn giản và dễ dàng.


3

Giải pháp dưới đây làm việc cho tôi, Chỉ cần thêm

u "Chuỗi"

(đại diện cho chuỗi là unicode) trước chuỗi của tôi.

result_html = result.to_html(col_space=1, index=False, justify={'right'})

text = u"""
<html>
<body>
<p>
Hello all, <br>
<br>
Here's weekly summary report.  Let me know if you have any questions. <br>
<br>
Data Summary <br>
<br>
<br>
{0}
</p>
<p>Thanks,</p>
<p>Data Team</p>
</body></html>
""".format(result_html)

3

Than ôi điều này hoạt động trong Python 3 ít nhất ...

Con trăn 3

Đôi khi lỗi nằm ở các biến môi trường và xảy ra như vậy

import os
import locale
os.environ["PYTHONIOENCODING"] = "utf-8"
myLocale=locale.setlocale(category=locale.LC_ALL, locale="en_GB.UTF-8")
... 
print(myText.encode('utf-8', errors='ignore'))

trong đó lỗi được bỏ qua trong mã hóa.


2

Tôi vừa gặp vấn đề này và Google đã dẫn tôi đến đây, vì vậy chỉ cần thêm vào các giải pháp chung ở đây, đây là điều làm việc cho tôi:

# 'value' contains the problematic data
unic = u''
unic += value
value = unic

Tôi đã có ý tưởng này sau khi đọc bài thuyết trình của Ned .

Tôi không yêu cầu để hiểu đầy đủ lý do tại sao điều này làm việc, mặc dù. Vì vậy, nếu bất cứ ai có thể chỉnh sửa câu trả lời này hoặc đưa ra nhận xét để giải thích, tôi sẽ đánh giá cao nó.


3
Là gì typecó giá trị? trước và sau này? Tôi nghĩ tại sao điều đó hoạt động là bằng cách thực hiện một thao unic += valuetác giống như unic = unic + valuebạn đang thêm một chuỗi và một unicode, trong đó python sau đó giả sử unicode cho kết quả unictức là loại chính xác hơn (nghĩ về khi bạn làm điều này a = float(1) + int(1), atrở thành một float) và sau đó value = unictrỏ valueđến unicđối tượng mới xảy ra là unicode.
Tom Mydd ERICn

2

Chúng tôi đã gặp lỗi này khi chạy manage.py migratetrong Django với đồ đạc được bản địa hóa.

Nguồn của chúng tôi chứa # -*- coding: utf-8 -*-khai báo, MySQL được cấu hình chính xác cho utf8 và Ubuntu có gói ngôn ngữ và giá trị phù hợp /etc/default/locale.

Vấn đề đơn giản là container Django (chúng tôi sử dụng docker) đã thiếu LANGenv var.

Thiết LANGđến en_US.UTF-8và khởi động lại chứa trước khi tái chạy di cư cố định vấn đề.


1

Nhiều câu trả lời ở đây (ví dụ @agf và @Andbdrew) đã giải quyết các khía cạnh trực tiếp nhất của câu hỏi OP.

Tuy nhiên, tôi nghĩ rằng có một khía cạnh tinh tế nhưng quan trọng đã bị bỏ qua phần lớn và điều đó rất quan trọng đối với tất cả những người như tôi đã kết thúc ở đây trong khi cố gắng hiểu ý nghĩa của mã hóa trong Python: Quản lý nhân vật Python 2 vs Python 3 rất khác nhau . Tôi cảm thấy như một khối lớn của sự nhầm lẫn ngoài kia có liên quan đến những người đọc về mã hóa trong Python mà không biết phiên bản.

Tôi đề nghị bất cứ ai quan tâm đến việc tìm hiểu nguyên nhân gốc rễ của vấn đề OP bắt đầu bằng cách đọc phần giới thiệu của Spolsky về biểu diễn ký tự và Unicode, sau đó chuyển sang Batchelder trên Unicode trong Python 2 và Python 3.


vâng, lỗi của tôi là do python 2.7, 'a'.format (u'ñ') và giải pháp chính xác là không sử dụng .encode ('utf-8') mà sử dụng luôn các chuỗi unicode, (mặc định trong python 3 ): u'a'.format (u'ñ '),
Rogelio

1

Cố gắng tránh chuyển đổi biến thành str (biến). Đôi khi, nó có thể gây ra vấn đề.

Mẹo đơn giản để tránh:

try: 
    data=str(data)
except:
    data = data #Don't convert to String

Ví dụ trên cũng sẽ giải quyết lỗi Mã hóa.


điều này không hoạt động vì bạn sẽ gặp phải lỗi trong ngoại trừ
Aurele Collinet

0

Nếu bạn có một cái gì đó giống như vậy packet_data = "This is data"thì hãy làm điều này trên dòng tiếp theo, ngay sau khi khởi tạo packet_data:

unic = u''
packet_data = unic


0

Tôi gặp vấn đề này khi cố gắng xuất các ký tự Unicode sang stdout, nhưng vớisys.stdout.write , thay vì in (để tôi cũng có thể hỗ trợ đầu ra cho một tệp khác).

Từ tài liệu riêng của BeautifulSoup , tôi đã giải quyết vấn đề này với thư viện codec:

import sys
import codecs

def main(fIn, fOut):
    soup = BeautifulSoup(fIn)
    # Do processing, with data including non-ASCII characters
    fOut.write(unicode(soup))

if __name__ == '__main__':
    with (sys.stdin) as fIn: # Don't think we need codecs.getreader here
        with codecs.getwriter('utf-8')(sys.stdout) as fOut:
            main(fIn, fOut)

0

Vấn đề này thường xảy ra khi một dự án django triển khai bằng Apache. Bởi vì Apache đặt biến môi trường LANG = C in / etc / sysconfig / httpd. Chỉ cần mở tệp và nhận xét (hoặc thay đổi thành flavior của bạn) cài đặt này. Hoặc sử dụng tùy chọn lang của lệnh WSGIDaemonProcess, trong trường hợp này, bạn sẽ có thể đặt biến môi trường LANG khác nhau cho các virtualhost khác nhau.


0

Giải pháp được đề xuất không hiệu quả với tôi và tôi có thể sống với việc bỏ tất cả các ký tự không phải ascii, vì vậy

s = s.encode('ascii',errors='ignore')

Điều đó đã để lại cho tôi một cái gì đó bị tước mà không ném lỗi.


0

Điều này sẽ làm việc:

 >>>print(unicodedata.normalize('NFD', re.sub("[\(\[].*?[\)\]]", "", "bats\xc3\xa0")).encode('ascii', 'ignore'))

Đầu ra:

>>>bats
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.