UnicodeEncodeError:“ latin-1”编解码器无法编码字符


93

当我尝试在数据库中插入外来字符时,可能是什么导致此错误?

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

我该如何解决呢?

谢谢!


40
db = MySQLdb.connect(host =“ localhost”,用户=“ root”,passwd =“”,db =“ testdb”,use_unicode = True,charset =“ utf8”)
KyungHoon Kim 2014年

哇,@ KyungHoonKim,您救了我的命!起来吧!
Florian Doyen '18

Answers:


64

字符U + 201C左双引号不在Latin-1(ISO-8859-1)编码中。

目前在代码页1252(西欧)。这是Windows特定的编码,基于ISO-8859-1,但会将额外的字符放入0x80-0x9F范围内。代码页1252通常与ISO-8859-1混淆,这是一种令人讨厌但现在是标准的Web浏览器行为,如果您将页面作为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 Western代码页中的其他字符。但是cp1252中不存在的其他Unicode字符仍然会导致错误。

您可以encode(..., 'ignore')通过消除字符来抑制错误,但实际上在本世纪,您应该在数据库和页面中都使用UTF-8。此编码允许使用任何字符。理想情况下,您还应该告诉MySQL您正在使用UTF-8字符串(通过在字符串列上设置数据库连接和排序规则),这样它就可以正确区分大小写并进行排序。


1
这不是cp1252ISO-8859-1的严格超集吗?即,当浏览器收到ISO-8859-1页面时,他们可以将其呈现为CP1252,因为0x80-0x9F无论如何该范围中都不会包含任何字符。
MSalters 2010年

3
不,在ISO-8859-1中,字节0x80–0x9F确实具有实际分配,但被cp1252的添加内容覆盖,因此它不是超集。它们完全映射到Unicode字符U + 0080–U + 009F,它们是控制字符的一部分。它们控制的字符很少使用,这就是为什么浏览器不使用它的原因,但是当您尝试转换字节为Unicode的序列时,这很烦人。
bobince 2010年

我唯一一次在编码为ISO-8859-1或UTF-8的文件中看到U + 0080-U + 009F范围内的字符是由于一些小丑将一堆文件串联在一起而造成的,其中一些文件是用cp850编码的然后将产生的混乱从“ latin1”转码为UTF-8。HTML5规范草案正在考虑使非常实用的浏览器行为(以及许多类似的情况)成圣
John Machin

94

使用Python MySQLdb模块时,我遇到了同样的问题。由于MySQL允许您将几乎任何所需的二进制数据存储在文本字段中,而不考虑字符集,因此我在这里找到了解决方案:

在Python MySQLdb中使用UTF8

编辑:引用以上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 2012年

@Fluffeh事实如此。
CatShoes

1
非常感谢,尝试了1000多种方法后,它就像是一种魅力。
Juergen Riemer

2
只有db.set_character_set('utf8')应该可以解决问题
Pandurang Patil

21

最好的解决方案是

  1. 将mysql的字符集设置为'utf-8'
  2. 确实喜欢此评论(添加use_unicode=Truecharset="utf8"

    db = MySQLdb.connect(host =“ localhost”,用户=“ root”,passwd =“”,db =“ testdb”,use_unicode = True,charset =“ utf8”)– KyungHoon Kim 2014年3月13日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

大!这正是我在寻找的东西
Geek

此外,我们最好要设定utf8mb4是否有针对MySQL emoji.etc,是指什么,是最差utf8mb4和-UTF8,字符集,在MySQL的间
切尼

20

我希望您的数据库至少为UTF-8。然后,您需要先运行,yourstring.encode('utf-8')然后再将其放入数据库中。


3

您正在尝试\u201c使用ISO-8859-1 / Latin-1无法描述该代码点的编码来存储Unicode代码点。您可能需要更改数据库以使用utf-8,并使用适当的编码来存储字符串数据,或者您可能想在存储内容之前清理输入内容;或者 即使用类似Sam Ruby的出色的i18n指南的内容。那将讨论windows-1252可能引起的问题,并建议如何处理,以及指向示例代码的链接!


2

SQLAlchemy用户只需将其字段指定为即可convert_unicode=True

例: sqlalchemy.String(1000, convert_unicode=True)

SQLAlchemy将只接受unicode对象并将其返回,从而处理编码本身。

文件


1

Latin-1(aka ISO 8859-1)是一个八位字节的字符编码方案,您不能将\u201c)放入一个字节中。

您是要使用UTF-8编码吗?


1
Latin-1会编码特定的 Unicode字符,但不是那个。\ u201c是否不能容纳在字节中没关系。Windows-1252也是一个八位字节编码方案,并且确实包含\ u201c。
Mark Tolonen

cp1253(又名Windows-1253)也是一个八位字节字符编码方案,但仍\u0391适合一个字节(特别是字节193)。您可能想看看;人们发现它很有帮助。
tzot 2010年

Unicode在16位代码点中合并了Latin-1 / cp1253字形。令我惊讶的是,这些评论似乎在反其道而行之。
msw

1

使用以下代码片段将文本从拉丁语转换为英语

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

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

输出:

'aeinouu'


-3

Python:您需要 在Python文件的第一行中添加 #-*-编码:UTF-8-*-(删除*周围的空格)。然后将以下内容添加到要编码的文本中:.encode('ascii','xmlcharrefreplace')。这会将所有的unicode字符替换为与ASCII等价的字符。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.