【问题标题】:UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa0 in position 180: invalid start byteUnicodeDecodeError:“utf-8”编解码器无法解码位置 180 中的字节 0xa0:无效的起始字节
【发布时间】:2021-10-28 09:42:42
【问题描述】:

我在 settings.py 中使用具有以下配置的 Django

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': '-',
        'USER': '-',
        'PASSWORD': '-',
        'HOST': '-',
        'PORT': '-',
        'OPTIONS': {'charset': 'utf8mb4'}
    }
}

数据库服务器正在 AWS RDS 上运行。我有两个 EC2 实例,其中一个能够运行完全相同的代码并获取相同的数据,而从第二个 EC2 我收到此错误:

     return self._execute_with_wrappers(sql  params  many=False  executor=self._execute)
File "/home/ubuntu/.virtualenvs/python39/lib/python3.9/site-packages/django/db/backends/utils.py"   line 75  in _execute_with_wrappers  
     return executor(sql     params  many    context)
File "/home/ubuntu/.virtualenvs/python39/lib/python3.9/site-packages/django/db/backends/utils.py"   line 84  in _execute    
     return self.cursor.execute(sql  params)        
File "/home/ubuntu/.virtualenvs/python39/lib/python3.9/site-packages/django/db/backends/mysql/base.py"  line 73  in execute 
     return self.cursor.execute(query    args)      
File "/home/ubuntu/.virtualenvs/python39/lib/python3.9/site-packages/MySQLdb/cursors.py"    line 206     in execute 
     res = self._query(query)           
File "/home/ubuntu/.virtualenvs/python39/lib/python3.9/site-packages/MySQLdb/cursors.py"    line 321     in _query  
     self._post_get_result()            
File "/home/ubuntu/.virtualenvs/python39/lib/python3.9/site-packages/MySQLdb/cursors.py"    line 355     in _post_get_result    
self._rows = self._fetch_row(0)         
File "/home/ubuntu/.virtualenvs/python39/lib/python3.9/site-packages/MySQLdb/cursors.py"    line 328     in _fetch_row  
     return self._result.fetch_row(size  self._fetch_type)      
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa0 in position 180: invalid start byte

django html 响应另外显示:

Unicode error hint
The string that could not be encoded/decoded was: \n<p>�</p>\

另外负责抛出错误的代码sn-p是:

    exp = MyModel.objects.all()
    **for e in exp:** <-- this line is throwing the error
        #do something

两台服务器上的版本:

EC2-1st 有:

Ubuntu 16.04.4

Django==1.11.2
mysqlclient==1.3.10
django-mysql==2.1.0

python3 --version
Python 3.5.2

mysql --version
mysql  Ver 14.14 Distrib 5.7.22, for Linux (x86_64) using  EditLine wrapper

同时 EC2-2nd 是 EC2-1st 的副本,应用了更新:

Ubuntu 20.04.3

Django==3.2.6
mysqlclient==2.0.3
django-mysql==3.10.0

python3 --version
Python 3.9.5

mysql --version
mysql  Ver 14.14 Distrib 5.7.35, for Linux (x86_64) using  EditLine wrapper

此外,我的本地服务器可以使用以下版本的工具正常运行: [我已使用接近 prod 配置的本地配置在本地导入 RDS db 以尝试调试问题]。

Mac OS 11.5.2
Django==3.2.6
mysqlclient==2.0.3
django-mysql==3.10.0

Python 3.9.6

mysql  Ver 8.0.25 for macos11.3 on x86_64 (Homebrew)

我应该尝试什么?

【问题讨论】:

标签: mysql django amazon-rds mysql-python django-mysql


【解决方案1】:

MySQL 文档Connect-Time Error Handling 描述了当您使用 MySQL 8.0 客户端库连接到具有 utf8mb4 字符集的 MySQL 5.7 服务器时出现的问题。 MySQL 8.0 客户端请求 utf8mb4_0900_ai_ci 排序规则,但 MySQL 5.7 服务器无法识别该排序规则,因此服务器静默回退到具有 latin1_swedish_ci 排序规则的 latin1 字符集。随后服务器发送latin1结果集,但客户端认为它正在接收utf8mb4,最终导致UnicodeDecodeError。作为一种解决方法,您必须明确地SET NAMES utf8mb4。我创建了一个问题mysqlclient#504 要求python 客户端每次都这样做。

要确认连接后字符集不正确,请仔细检查服务器的值character_set_client(解释语句的字符集)、character_set_connection(语句转换为的字符集)和character_set_results(结果集作为发送的字符集)。如果他们是latin1尽管客户端连接为utf8mb4,那么这个bug可能被触发了。

with con.cursor() as c:
  c.execute("show variables like 'character_set_%'")
  for row in c:
    print(row)
(b'character_set_client', b'latin1')
(b'character_set_connection', b'latin1')
(b'character_set_database', b'latin1')
(b'character_set_filesystem', b'binary')
(b'character_set_results', b'latin1')
(b'character_set_server', b'latin1')
(b'character_set_system', b'utf8')
(b'character_sets_dir', b'/usr/share/mysql/charsets/')

我认为该问题的解决方法是在连接后执行以下操作:

# explicitly set connection charset to the same as MySQLdb.connect()
con.query("SET NAMES utf8mb4")
con.store_result()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-12
    • 1970-01-01
    • 2023-01-11
    • 2021-06-12
    • 1970-01-01
    • 2022-05-30
    • 2021-12-01
    • 2016-05-13
    相关资源
    最近更新 更多