UnicodeEncodeError: кодек latin-1 не может кодировать символ


96

Что может вызвать эту ошибку, когда я пытаюсь вставить чужой символ в базу данных?

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

И как мне это решить?

Благодарность!


40
db = MySQLdb.connect (host = "localhost", user = "root", passwd = "", db = "testdb", use_unicode = True, charset = "utf8")
KyungHoon Kim

вау, @KyungHoonKim, ты спас мне жизнь! Вы идете!
Флориан Дойен

Ответы:


66

Символ U + 201C с левыми двойными кавычками отсутствует в кодировке Latin-1 (ISO-8859-1).

Он находится присутствует в кодовой странице 1252 (западноевропейская). Это специфичная для Windows кодировка, основанная на ISO-8859-1, но добавляющая дополнительные символы в диапазон 0x80-0x9F. Кодовую страницу 1252 часто путают с ISO-8859-1, и это раздражает, но теперь стандартное поведение веб-браузера: если вы обслуживаете свои страницы как ISO-8859-1, браузер вместо этого будет рассматривать их как cp1252. Однако на самом деле это две разные кодировки:

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

Если вы используете свою базу данных только как хранилище байтов, вы можете использовать cp1252 для кодирования и других символов, присутствующих на западной кодовой странице Windows. Но все же другие символы Unicode, которых нет в cp1252, вызовут ошибки.

Вы можете использовать encode(..., 'ignore')для подавления ошибок, избавившись от символов, но на самом деле в этом веке вы должны использовать UTF-8 как в своей базе данных, так и на своих страницах. Эта кодировка позволяет использовать любой символ. В идеале вы также должны сообщить MySQL, что используете строки UTF-8 (установив соединение с базой данных и сопоставление для строковых столбцов), чтобы можно было получить сравнение и сортировку без учета регистра.


1
Разве это не cp1252строгий расширенный набор ISO-8859-1? Т.е. когда браузеры получают страницу ISO-8859-1, они могут отобразить ее так, как если бы это была CP1252, потому что в 0x80-0x9Fлюбом случае не будет никаких символов из диапазона .
MSalters

3
Нет, байты 0x80–0x9F действительно имеют реальные назначения в ISO-8859-1, которые переопределяются добавлением cp1252, поэтому это не надмножество. Они точно соответствуют символам Unicode U + 0080 – U + 009F, которые представляют собой набор управляющих символов. Это управляющие символы, которые не используются очень часто, поэтому браузерам это сошло с рук, но это раздражает, когда вы пытаетесь преобразовать последовательности байтов в Unicode.
bob с

Единственный раз, когда я видел символы в диапазоне U + 0080-U + 009F в файле, закодированном как ISO-8859-1 или UTF-8, был результатом того, что какой-то клоун объединил кучу файлов, некоторые из которых были закодированы в cp850 а затем перекодировать полученный беспорядок с "latin1" в UTF-8. Черновик спецификации HTML5 рассматривает возможность освящения этого очень практичного поведения браузера (и целого ряда подобных случаев) - см. Whatwg.org/specs/web-apps/current-work/multipage/…
Джон Мачин

94

Я столкнулся с этой же проблемой при использовании модуля Python MySQLdb. Поскольку MySQL позволяет хранить практически любые двоичные данные в текстовом поле независимо от набора символов, я нашел здесь свое решение:

Использование UTF8 с Python MySQLdb

Изменить: цитата из приведенного выше URL-адреса, чтобы удовлетворить запрос в первом комментарии ...

"UnicodeEncodeError: кодек 'latin-1' не может кодировать символ ..."

Это потому, что MySQLdb обычно пытается все кодировать в latin-1. Это можно исправить, выполнив следующие команды сразу после того, как вы установили соединение:

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

«db» - это результат MySQLdb.connect(), а «dbc» - результат db.cursor().


1
Предполагается, что соответствующая часть связанного элемента указана в ответе. Ссылка для дополнительного чтения отличная, но, пожалуйста, попробуйте вставить краткое изложение в свой ответ, так сказать :)
Fluffeh

@Fluffeh Так и было.
CatShoes

1
Большое спасибо, работал как шарм после того, как попробовал 1000 других вещей.
Juergen Riemer

2
Только db.set_character_set ('utf8') должен решить проблему
Пандуранг Патил

21

Лучшее решение -

  1. установите кодировку mysql на 'utf-8'
  2. нравится этот комментарий (добавить use_unicode=Trueи charset="utf8")

    db = MySQLdb.connect (host = "localhost", user = "root", passwd = "", db = "testdb", use_unicode = True, charset = "utf8") - KyungHoon Kim 13 марта '14 в 17:04

подробнее см.:

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.

        """

1
Этот ответ требует больше голосов. Это чистое решение, очищающее прикладной уровень от ненужных накладных расходов на кодирование.
yeaske 08

Большой! Это именно то, что я искал
Компьютерщик

Кроме того, нам лучше установить utf8mb4для mysql, если у вас есть emoji.etc, обратитесь к тому, что-есть-разница-между-utf8mb4-и-utf8-charsets-in-mysql
Чейни

20

Надеюсь, ваша база данных не ниже UTF-8. Затем вам нужно будет запустить его, yourstring.encode('utf-8')прежде чем пытаться поместить его в базу данных.


3

Вы пытаетесь сохранить кодовую точку Unicode, \u201cиспользуя кодировку, ISO-8859-1 / Latin-1которая не может описать эту кодовую точку. Либо вам может потребоваться изменить базу данных для использования utf-8 и сохранить строковые данные с использованием соответствующей кодировки, либо вы можете захотеть очистить свои входные данные перед сохранением содержимого; т.е. используя что-то вроде отличного руководства Сэма Руби по i18n . Это говорит о проблемах, которые windows-1252могут вызвать, и предлагает, как их обработать, а также ссылки на образец кода!


2

Пользователи SQLAlchemy могут просто указать свое поле как convert_unicode=True.

Пример: sqlalchemy.String(1000, convert_unicode=True)

SQLAlchemy просто примет объекты Unicode и вернет их обратно, обрабатывая саму кодировку.

Документы


2

Используйте приведенный ниже фрагмент, чтобы преобразовать текст с латыни на английский.

import unicodedata
def strip_accents(text):
    return "".join(char for char in
                   unicodedata.normalize('NFKD', text)
                   if unicodedata.category(char) != 'Mn')

strip_accents('áéíñóúü')

выход:

'aeinouu'


1

Latin-1 (также известный как ISO 8859-1 ) - это схема кодирования символов с одним октетом, и вы не можете поместить \u201c( ) в байт.

Вы хотели использовать кодировку UTF-8?


1
Latin-1 кодирует определенные символы Unicode, только не этот. Не имеет значения, что \ u201c не помещается в байт. Windows-1252 является одной схемы кодирования октет также, и это в том числе \ u201c.
Марк Толонен

cp1253 (он же windows-1253) также является схемой кодирования символов с одним октетом, но при этом \u0391отлично подходит для байта (в частности, байта 193). Вы можете взглянуть на это ; люди нашли это полезным.
tzot

Unicode включает глифы Latin-1 / cp1253 в виде 16-битных кодовых точек. Я удивлен, что комментарии, кажется, утверждают обратное.
msw

-3

Python: вам нужно будет добавить # - * - coding: UTF-8 - * - (удалить пробелы вокруг *) в первую строку файла python. а затем добавьте в текст, который нужно кодировать, следующее: .encode ('ascii', 'xmlcharrefreplace') . Это заменит все символы Юникода его эквивалентом ASCII.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.