2010-10-15 4 views
51

Điều gì có thể gây ra lỗi này khi tôi cố chèn một ký tự nước ngoài vào cơ sở dữ liệu?UnicodeEncodeError: codec 'latin-1' không thể mã hóa ký tự

>>UnicodeEncodeError: 'latin-1' codec can't encode character u'\u201c' in position 0: ordinal not in range(256) 

Và làm cách nào để giải quyết?

Cảm ơn!

+27

db = MySQLdb.connect (host = "localhost", user = "root", passwd = "", db = "TestDB", use_unicode = True, charset = "utf8") –

Trả lời

44

Ký tự U + 201C Dấu ngoặc kép trái không có trong mã hóa Latin-1 (ISO-8859-1).

hiện diện trong trang mã 1252 (Tây Âu). Đây là một mã hóa dành riêng cho Windows dựa trên ISO-8859-1 nhưng đặt ký tự thừa vào phạm vi 0x80-0x9F. Trang mã 1252 thường bị nhầm lẫn với ISO-8859-1, và đó là một hành vi trình duyệt web gây phiền nhiễu nhưng hiện nay, nếu bạn phục vụ các trang của mình dưới dạng ISO-8859-1, trình duyệt sẽ xử lý chúng dưới dạng cp1252. Tuy nhiên, họ thực sự là hai mã hóa riêng biệt:

>>> u'He said \u201CHello\u201D'.encode('iso-8859-1') 
UnicodeEncodeError 
>>> u'He said \u201CHello\u201D'.encode('cp1252') 
'He said \x93Hello\x94' 

Nếu bạn đang sử dụng cơ sở dữ liệu của bạn chỉ như là một cửa hàng byte, bạn có thể sử dụng để mã hóa cp1252 và các nhân vật khác hiện diện trong trang mã Windows tiếng Tây. Nhưng vẫn còn các ký tự Unicode khác không có trong cp1252 sẽ gây ra lỗi.

Bạn có thể sử dụng encode(..., 'ignore') để ngăn chặn các lỗi bằng cách loại bỏ các ký tự, nhưng thực sự trong thế kỷ này bạn nên sử dụng UTF-8 trong cả cơ sở dữ liệu và trang của bạn. Mã hóa này cho phép sử dụng bất kỳ ký tự nào. Bạn cũng nên lý tưởng cho MySQL biết bạn đang sử dụng các chuỗi UTF-8 (bằng cách thiết lập kết nối cơ sở dữ liệu và đối chiếu trên các cột chuỗi), vì vậy nó có thể so sánh và sắp xếp phân biệt dạng chữ.

+0

Không phải là 'cp1252' là bộ siêu nhạy sáng ISO-8859-1? I E. khi các trình duyệt nhận được trang ISO-8859-1, chúng có thể hiển thị nó như thể nó là CP1252 bởi vì sẽ không có bất kỳ ký tự nào trong dải '0x80-0x9F'. – MSalters

+3

Không, các byte 0x80–0x9F có các phép gán thực trong ISO-8859-1, được ghi đè bởi các bổ sung của cp1252 do đó nó không phải là một siêu dữ liệu. Chúng ánh xạ chính xác đến các ký tự Unicode U + 0080 – U + 009F, là một lựa chọn các ký tự điều khiển. Họ là những nhân vật điều khiển không được sử dụng nhiều, đó là lý do tại sao các trình duyệt đã bỏ qua nó, nhưng nó gây phiền nhiễu khi bạn đang cố gắng chuyển đổi một chuỗi byte-as-Unicode. – bobince

+0

Thời gian duy nhất mà tôi từng thấy các ký tự trong phạm vi U + 0080-U + 009F trong một tệp được mã hóa dưới dạng ISO-8859-1 hoặc UTF-8 do một số chú hề ghép nối một loạt tệp. cp850 và sau đó transcoding mess kết quả từ "latin1" thành UTF-8. Dự thảo HTML5 spec đang xem xét việc thánh hóa hành vi trình duyệt rất thực tế (và toàn bộ các trường hợp tương tự) - xem http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html# character-encodings-0 –

3

Bạn đang cố gắng lưu trữ một điểm mã Unicode \u201c bằng cách sử dụng mã hóa ISO-8859-1/Latin-1 không thể mô tả điểm mã đó. Hoặc bạn có thể cần phải thay đổi cơ sở dữ liệu để sử dụng utf-8 và lưu trữ dữ liệu chuỗi bằng cách sử dụng mã hóa thích hợp hoặc bạn có thể muốn khử trùng các đầu vào của mình trước khi lưu trữ nội dung; tức là sử dụng something like Sam Ruby's excellent i18n guide. Điều đó nói về các vấn đề mà windows-1252 có thể gây ra và đề xuất cách xử lý vấn đề, cộng với các liên kết đến mã mẫu!

1

Latin-1 (aka ISO 8859-1) là một lược đồ mã hóa ký tự octet duy nhất và bạn không thể phù hợp với \u201c () thành một byte.

Ý của bạn là sử dụng mã hóa UTF-8?

+1

Latin- 1 mã hóa _specific_ Unicode ký tự, chỉ cần không phải là một. Nó không quan trọng nếu \ u201c không thể phù hợp với một byte. windows-1252 cũng là một lược đồ mã hóa octet đơn và _does_ bao gồm \ u201c. –

+0

cp1253 (còn gọi là windows-1253) cũng là một lược đồ mã hóa ký tự octet, và '\ u0391' phù hợp với một byte (cụ thể, byte 193). Bạn * có thể * muốn xem [rằng] (http://stackoverflow.com/questions/368805/python-unicodedecodeerror-am-i-misunderstanding-encode/370199#370199); mọi người thấy nó hữu ích. – tzot

+0

Unicode kết hợp các ký tự Latin-1/cp1253 dưới dạng các điểm mã 16 bit. Tôi ngạc nhiên rằng các ý kiến ​​dường như đang tuyên bố ngược lại. – msw

17

Tôi hy vọng cơ sở dữ liệu của bạn ít nhất là UTF-8. Sau đó, bạn sẽ cần phải chạy yourstring.encode('utf-8') trước khi bạn thử đưa nó vào cơ sở dữ liệu.

+0

câu trả lời rất hữu ích! cảm ơn! –

66

Tôi đã gặp vấn đề tương tự khi sử dụng mô-đun MySQLdb Python. Kể từ MySQL sẽ cho phép bạn lưu trữ chỉ là về bất kỳ dữ liệu nhị phân mà bạn muốn trong một lĩnh vực văn bản không phân biệt bộ ký tự, tôi thấy giải pháp của tôi ở đây:

Using UTF8 with Python MySQLdb

Chỉnh sửa: Trích dẫn từ URL ở trên để đáp ứng các yêu cầu trong bình luận đầu tiên ...

"UnicodeEncodeError:'latin-1' codec can't encode character ..."

This is because MySQLdb normally tries to encode everythin to latin-1. This can be fixed by executing the following commands right after you've etablished the connection:

db.set_character_set('utf8') 
dbc.execute('SET NAMES utf8;') 
dbc.execute('SET CHARACTER SET utf8;') 
dbc.execute('SET character_set_connection=utf8;') 

"db" is the result of MySQLdb.connect() , and "dbc" is the result of db.cursor() .

+0

Đề xuất rằng phần liên quan của một mục được liên kết được cung cấp trong câu trả lời.Các liên kết để đọc thêm là rất tốt, nhưng hãy cố gắng để pop trong một bản tóm tắt điều hành trong câu trả lời của bạn để nói chuyện :) – Fluffeh

+0

@ Fluffeh Và nó là như vậy. – CatShoes

+0

@CatShoes Và một upvote đã được thực hiện :) – Fluffeh

-2

Python: Bạn sẽ cần phải thêm # - * - mã hóa: UTF-8 - * - (loại bỏ các khoảng trống xung quanh *) vào dòng đầu tiên của python tập tin. và sau đó thêm nội dung sau vào văn bản để mã hóa: .encode ('ascii', 'xmlcharrefreplace'). Điều này sẽ thay thế tất cả các ký tự unicode với nó tương đương ASCII.

10

Giải pháp tốt nhất là charset

  1. bộ mysql để 'utf-8'
  2. làm như nhận xét này (thêm use_unicode=Truecharset="utf8")

    db = MySQLdb.connect(host="localhost", user = "root", passwd = "", db = "testdb", use_unicode=True, charset="utf8") – KyungHoon Kim Mar 13 '14 at 17:04

chi tiết xem:

class Connection(_mysql.connection): 

    """MySQL Database Connection Object""" 

    default_cursor = cursors.Cursor 

    def __init__(self, *args, **kwargs): 
     """ 

     Create a connection to the database. It is strongly recommended 
     that you only use keyword parameters. Consult the MySQL C API 
     documentation for more information. 

     host 
      string, host to connect 

     user 
      string, user to connect as 

     passwd 
      string, password to use 

     db 
      string, database to use 

     port 
      integer, TCP/IP port to connect to 

     unix_socket 
      string, location of unix_socket to use 

     conv 
      conversion dictionary, see MySQLdb.converters 

     connect_timeout 
      number of seconds to wait before the connection attempt 
      fails. 

     compress 
      if set, compression is enabled 

     named_pipe 
      if set, a named pipe is used to connect (Windows only) 

     init_command 
      command which is run once the connection is created 

     read_default_file 
      file from which default client values are read 

     read_default_group 
      configuration group to use from the default file 

     cursorclass 
      class object, used to create cursors (keyword only) 

     use_unicode 
      If True, text-like columns are returned as unicode objects 
      using the connection's character set. Otherwise, text-like 
      columns are returned as strings. columns are returned as 
      normal strings. Unicode objects will always be encoded to 
      the connection's character set regardless of this setting. 

     charset 
      If supplied, the connection character set will be changed 
      to this character set (MySQL-4.1 and newer). This implies 
      use_unicode=True. 

     sql_mode 
      If supplied, the session SQL mode will be changed to this 
      setting (MySQL-4.1 and newer). For more details and legal 
      values, see the MySQL documentation. 

     client_flag 
      integer, flags to use or 0 
      (see MySQL docs or constants/CLIENTS.py) 

     ssl 
      dictionary or mapping, contains SSL connection parameters; 
      see the MySQL documentation for more details 
      (mysql_ssl_set()). If this is set, and the client does not 
      support SSL, NotSupportedError will be raised. 

     local_infile 
      integer, non-zero enables LOAD LOCAL INFILE; zero disables 

     autocommit 
      If False (default), autocommit is disabled. 
      If True, autocommit is enabled. 
      If None, autocommit isn't set and server default is used. 

     There are a number of undocumented, non-standard methods. See the 
     documentation for the MySQL C API for some hints on what they do. 

     """ 
+0

Câu trả lời này cần nhiều ưu điểm hơn. Đây là giải pháp sạch, xóa lớp ứng dụng các chi phí mã hóa không cần thiết. – yeaske

2

Người dùng SQLAlchemy chỉ có thể chỉ định trường của họ là convert_unicode=True.

Ví dụ: sqlalchemy.String(1000, convert_unicode=True)

SQLAlchemy chỉ đơn giản là sẽ chấp nhận đối tượng unicode và trả lại trở lại, xử lý mã hóa riêng của mình.

Docs