UnicodeEncodeError:“ascii”编解码器无法编码字符
Posted
技术标签:
【中文标题】UnicodeEncodeError:“ascii”编解码器无法编码字符【英文标题】:UnicodeEncodeError: 'ascii' codec can't encode character 【发布时间】:2011-04-12 13:35:19 【问题描述】:上传包含非 ASCII 字符的文件时,出现 UnicodeEncodeError:
Exception Type: UnicodeEncodeError at /admin/studio/newsitem/add/
Exception Value: 'ascii' codec can't encode character u'\xf8' in position 78: ordinal not in range(128)
见full stack trace。
我使用 mysql、nginx 和 FastCGI 运行 Django 1.2。
这是根据Django Trac database修复的问题,但我还是有这个问题。欢迎任何有关如何修复的建议。
编辑:这是我的图像字段:
image = models.ImageField(_('image'), upload_to='uploads/images', max_length=100)
【问题讨论】:
您也可以给出模型/字段定义吗?特别是我有兴趣看到upload_to
的定义。
更新了 upload_to 定义。
对于仍然登陆这里的任何人,请查看 akaihola 的 Django 票证的最后评论,他说:“Debian 默认使用 LANG=C 语言环境运行 Apache,这至少会中断上传名称中包含特殊字符的文件使用 mod_wsgi 运行时。在 /etc/apache2/envvars 中激活 UTF-8 语言环境应该可以解决问题“票证:code.djangoproject.com/ticket/6009
这也适用于 nginx。在这里查看我的答案:***.com/a/7602446/108763
【参考方案1】:
对于在使用Supervisor 运行 Django 时遇到此问题的任何人,解决方案是添加例如在 Supervisor 配置的 supervisord
部分添加以下内容:
environment=LANG="en_US.utf8", LC_ALL="en_US.UTF-8", LC_LANG="en_US.UTF-8"
这解决了我在 Debian Squeeze 上运行的 Supervisor 3.0a8 的问题。
还要确保 Supervisor 通过运行重新读取配置:
supervisorctl reread
supervisorctl restart myservice
(感谢@Udi)
对于新贵,请添加您的/etc/init/myservice.conf
:
env LANG="en_US.utf8"
env LC_ALL="en_US.UTF-8"
env LC_LANG="en_US.UTF-8"`
(感谢 @Andrii Zarubin;有关更多信息,请参阅 Upstart 文档中的 Environment Variables)
【讨论】:
确保 /etc/init.d/supervisor stop 和 /etc/init.d/supervisor start 以使更改生效。只是重新启动是行不通的。 如果您收到此错误键/值对的意外结束,您将需要引用这些值。例如环境=LANG='en_US.utf8'。 lists.supervisord.org/pipermail/supervisor-users/2010-March/… 您可以使用supervisorctl reread
和supervisorctl restart myservice
强制读取配置文件,而不是停止和启动整个守护进程。
遗憾的是,我不能足够支持这个答案,你真的救了我的星期天,谢谢!
如果您使用的是upstart - 您必须添加env LANG="en_US.utf8" env LC_ALL="en_US.UTF-8" env LC_LANG="en_US.UTF-8"
【参考方案2】:
在您必须在仅接受 ascii 的位置(如控制台或作为路径)显示 unicode 字符串的情况下,您必须告诉 Python 您希望它尽最大努力替换非 ascii 字符。
>> problem_str = u'This is not all ascii\xf8 man'
>> safe_str = problem_str.encode('ascii', 'ignore')
>> safe_str
'This is not all ascii man'
通过谨慎处理 Django 模板在管理员中防止了编码问题,但是如果您曾经添加自定义列并且忘记将值转换为 ascii,或者您覆盖了 str 方法模型而忘记执行此操作,您将得到相同的错误,从而阻止模板渲染。
如果将此字符串保存到您的(希望是 utf8)数据库中就没有问题,看起来您正在尝试上传一个文件,该文件使用具有非 ascii 字符的实体的标题。
【讨论】:
谢谢!在对一个简单的问题进行无果搜索后,我偶然发现了这个答案:如何在 Python 中发送包含非拉丁字符的电子邮件?您的解决方案有效!【参考方案3】:希望这会有所帮助。 就我而言,我正在通过 daemontools 运行 django。
设置
export LANG='en_US.UTF-8'
export LC_ALL='en_US.UTF-8'
在执行manage.py之前运行脚本解决了上传文件名的问题
【讨论】:
【参考方案4】:在对此进行了更多调查后,我发现我没有在我的主 Nginx 配置文件中设置字符集:
http
charset utf-8;
通过添加上面的,问题就消失了,我认为这是处理这个问题的正确方法。
【讨论】:
这只有在 nginx 直接运行后端代码时才有效。假设它是 gunicorn 或 uwsgi 之类的代理,您将必须配置 wsgi 服务器的环境以使用 UTF-8。将此添加到您的 Nginx 配置中并没有什么坏处,但它可能无法解决您的问题。 正如@amjoconn 已经提到的,在我的情况下,通过在我的 uwsgi-config 文件中添加“env = LC_ALL=ru_RU.UTF-8”解决了这个问题【参考方案5】:akaihola 的回答很有帮助。对于那些使用通过 upstart 脚本管理的 uWSGI 运行 django 应用程序的人,只需将这些行添加到您的 /etc/init/yourapp.conf
env LANG="en_US.utf8"
env LC_ALL="en_US.UTF-8"
env LC_LANG="en_US.UTF-8"
它为我解决了问题。
【讨论】:
谢谢!这就是解决我问题的方法!env LANG="en_US.UTF-8" env LC_ALL="en_US.UTF-8" env LC_LANG="en_US.UTF-8"
。请注意,它是 env
而不是 export
。这是在 System V 脚本 (/etc/init/xxx.conf) 下使用的语法。这个错误花了我几个小时。【参考方案6】:
如前所述,它与语言环境有关。例如,如果您使用gunicorn
为您的django application
提供服务,您可能有一个init.d
脚本(或者像我一样,一个runit 脚本),您可以在其中设置语言环境。
要解决文件上传时出现的 UnicodeEncodeError,请在运行应用的脚本中添加 export LC_ALL=en_US.UTF8
之类的内容。
例如,这是我的(使用gunicorn
和runit
):
#!/bin/bash
export LC_ALL=en_US.UTF8
cd /path/to/app/projectname
exec gunicorn_django -b localhost:8000 --workers=2
此外,您可以在模板中检查您的语言环境,在您的视图中使用:
import locale
data_to_tpl = 'loc': locale.getlocale(), 'lod_def': locale.getdefaultlocale()
只需在您的模板中显示loc - loc_def
。
您将获得有关您的区域设置的更多信息!这对我很有用。
【讨论】:
【参考方案7】:没有看到更多代码很难说,但它看起来与这个问题有关:UnicodeDecodeError on attempt to save file through django default filebased backend。
查看提到的 Django 票证,您似乎应该遵循类似于“如果遇到 UnicodeEncodeError”的部署文档的内容:https://docs.djangoproject.com/en/1.4/howto/deployment/modpython/#if-you-get-a-unicodeencodeerror
(我知道这是针对 Apache/mod_python 的,但我猜这与文件系统编码不是 UTF-8 的根本问题相同,使用 nginx 时也有类似的修复)
编辑: 据我所知,这个 nginx 模块将是等效的修复:http://wiki.nginx.org/NginxHttpCharsetModule
【讨论】:
我怀疑这可能与此有关。我尝试在字符串前面添加一个 u ,如此处所述:***.com/questions/2457087/… 没有运气。你有 nginx 修复的链接吗? 谢谢,不过还是不行。我已经尝试设置区域设置,如 Django 文档中所示,还尝试将 charset utf8 添加到我的 nginx 配置中。也许我只需要重写保存方法来重命名文件…… 文档的链接已失效。【参考方案8】:另一个避免重写代码的有用选项是更改 python 的默认编码。
如果您使用的是virtualenv,您可以更改(如果不存在则创建)env/lib/python2.7/sitecustomize.py
并添加:
import sys
sys.setdefaultencoding('utf-8')
或者,如果你在生产系统中,你可以对/usr/lib/python2.7/sitecustomize.py
做同样的事情
【讨论】:
【参考方案9】:如果您使用的是 django 和 python 2.7,这会为我解决这个问题:
@python_2_unicode_compatible
class Utente(models.Model):
见https://docs.djangoproject.com/en/dev/ref/utils/#django.utils.encoding.python_2_unicode_compatible
【讨论】:
【参考方案10】:使用 python 2.7.8 和 Django 1.7,我通过导入解决了我的问题:
from __future__ import unicode_literals
并使用force_text()
:
from django.utils.encoding import force_text
【讨论】:
【参考方案11】:只是建立在这个帖子和其他人的答案上......
在尝试上传包含非 ASCII 字符的文件名时,我遇到了 genericpath.py 给出 UnicodeEncodeError 的相同问题。
我在 python 2.7 中使用 nginx、uwsgi 和 django。
在本地一切正常,但在服务器上却不行
这是我采取的步骤 1.添加到/etc/nginx/nginx.conf(没有解决问题)
http
charset utf-8;
我将此行添加到 etc/default/locale(没有解决问题)
LANGUAGE="en_US.UTF-8"
我按照“成功”标题下列出的说明进行操作 https://code.djangoproject.com/wiki/ExpectedTestFailures(没有解决问题)
aptitude install language-pack-en-base
在这张票证中找到 https://code.djangoproject.com/ticket/17816 这建议测试服务器上的视图以了解区域设置信息发生的情况
在你看来
import locale
locales = "Current locale: %s %s -- Default locale: %s %s" % (locale.getlocale() + locale.getdefaultlocale())
在您的模板中
locales
对我来说,问题是我的 Ubuntu 服务器上没有语言环境和默认语言环境(尽管我在本地 OSX 开发机器上确实有它们)然后具有非 ASCII 文件名/路径的文件将无法使用 python 正确上传引发 UnicodeEncodeError,但仅在生产服务器上。
解决方案
我将此添加到我的站点和站点管理员 uwsgi 配置文件中 例如/etc/uwsgi-emperor/vassals/my-site-config-ini 文件
env = LANG=en_US.utf8
【讨论】:
如何将它添加到 Apache2 站点配置中?【参考方案12】:没有一个答案对我有用(在 Ubuntu 上使用 Apache 和 Django 1.10);我选择从文件名中删除重音符号(规范化),如下所示:
def remove_accents(value):
nkfd_form = unicodedata.normalize('NFKD', str(value))
return "".join([c for c in nkfd_form if not unicodedata.combining(c)])
uploaded_file = self.cleaned_data['data']
# We need to remove accents to get rid of "UnicodeEncodeError: 'ascii' codec can't encode character" on Ubuntu
uploaded_file.name = remove_accents(uploaded_file.name)
【讨论】:
以上是关于UnicodeEncodeError:“ascii”编解码器无法编码字符的主要内容,如果未能解决你的问题,请参考以下文章
UnicodeEncodeError: 'ascii' 编解码器无法编码字符 u'\u2026'
UnicodeEncodeError: 'ascii' 编解码器无法编码字符 u'\u2013'
UnicodeEncodeError:'ascii'编解码器无法对特殊名称的字符进行编码[重复]
UnicodeEncodeError:'ascii' 编解码器无法在位置 0 编码字符 u'\xef':序数不在范围内(128)
UnicodeEncodeError:'ascii'编解码器无法在位置 3 编码字符 u'\ufffd':序数不在范围内(128)[重复]
UnicodeEncodeError:“ascii”编解码器无法在位置 126 编码字符 u'\u2019':序数不在范围内(128)