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。

我使用 mysqlnginx 和 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 rereadsupervisorctl 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 之类的内容。

例如,这是我的(使用gunicornrunit):

#!/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)