UnicodeEncodeError:'ascii'编解码器不能编码字符

当上传非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) 

查看完整的堆栈跟踪 。

我用MySQL和nginx和FastCGI运行Django 1.2。

这是一个根据Django Trac数据库修复的问题,但是我仍然有问题。 任何build议如何解决是受欢迎的。

编辑:这是我的形象领域:

 image = models.ImageField(_('image'), upload_to='uploads/images', max_length=100) 

对于在Supervisor中运行Django时遇到这个问题的人来说,解决办法是在Supervisorconfiguration的supervisord部分添加如下内容:

 environment=LANG="en_US.utf8", LC_ALL="en_US.UTF-8", LC_LANG="en_US.UTF-8" 

这解决了在Debian Squeeze上运行的Supervisor 3.0a8中的问题。

在必须在只接受ascii(如控制台或path)的地方显示unicodestring的情况下,您必须告诉Python您希望它尽可能地replace非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模板的谨慎处理中,编码问题在pipe理中是被阻止的,但是如果你曾经添加过自定义列并且忘记将值转换为ascii,或者你重写模型的str方法而忘记这么做,你将会得到同样的错误,防止模板渲染。

如果这个string被保存到你的(希望是utf8)数据库中,那就没有问题了,看起来你正在尝试上传一个使用非ascii字符的实体标题的文件。

希望这会有所帮助。 就我而言,我通过daemontools运行django。

设置

 export LANG='en_US.UTF-8' export LC_ALL='en_US.UTF-8' 

在运行脚本之前执行manage.py解决了上传文件名的问题

在调查了一些后,我发现我没有在我的主要Nginxconfiguration文件中设置字符集:

 http { charset utf-8; } 

通过增加上述内容,问题就消失了,我认为这是处理这个问题的正确方法。

akaihola的答案是有帮助的。 对于那些通过upstart脚本来pipe理由uWSGIpipe理的django应用的人,只需将这些行添加到/etc/init/yourapp.conf

 env LANG="en_US.utf8" env LC_ALL="en_US.UTF-8" env LC_LANG="en_US.UTF-8" 

它解决了我的问题。

如前所述,它与locale有关。 例如,如果你使用gunicorn来为你的django application提供服务,你可能会有一个init.d脚本(或者像我这样的runit脚本),你可以在其中设置语言环境。

要解决file upload中的UnicodeEncodeError问题,请在运行应用程序的脚本中inputexport 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}}

您将获得有关您的区域设置的更多信息! 这对我来说非常有用。

很难说没有看到更多的代码,但它看起来与这个问题有关: UnicodeDecodeError尝试通过django默认的基于文件的后端保存文件 。

通过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

避免重写代码的另一个有用的选项是更改python的默认编码。

如果你使用的是virtualenv,你可以改变(或创build如果不存在) env/lib/python2.7/sitecustomize.py并添加:

 import sys sys.setdefaultencoding('utf-8') 

或者,如果您在生产系统中,则可以对/usr/lib/python2.7/sitecustomize.py执行相同的操作

如果你使用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

使用Python 2.7.8和Django 1.7,我通过导入解决了我的问题:

 from __future__ import unicode_literals 

和使用force_text()

 from django.utils.encoding import force_text 

只是build立在这个线程和其他人的答案…

在尝试上传非ASCII字符的文件名时,我遇到了与genericpath.py相同的问题,它提供了一个UnicodeEncodeError。

我用python 2.7使用nginx,uwsgi和django。

一切工作本地,但不在服务器上

这里是我采取的步骤1.添加到/etc/nginx/nginx.conf(没有解决问题)

 http { charset utf-8; } 
  1. 我把这行添加到etc / default / locale(没有解决问题)

LANGUAGE = “的en_US.UTF-8”

  1. 我遵循这里列出的“成功”标题下的说明https://code.djangoproject.com/wiki/ExpectedTestFailures (没有解决问题)

     aptitude install language-pack-en-base 
  2. https://code.djangoproject.com/ticket/17816上find了这个问题,这个问题build议在服务器上testing一个视图,看看区域设置信息;

在你看来

 import locale locales = "Current locale: %s %s -- Default locale: %s %s" % (locale.getlocale() + locale.getdefaultlocale()) 

在你的模板中

 {{ locales }} 

对我来说,问题是我的Ubuntu服务器上没有语言环境和默认语言环境(尽pipe我的本地OSX开发机器上有它们),那么带有非ASCII文件名/path的文件将无法正确上传,导致Python引发UnicodeEncodeError ,但只在生产服务器上。

我把这个添加到我的网站和我的网站pipe理员uwsgiconfiguration文件例如/ etc / uwsgi-emperor / vassals / my-site-config-ini文件

 env = LANG=en_US.utf8 

没有答案为我工作(在Ubuntu上与Django 1.10使用Apache); 我select从文件名(normalize)中删除重音符号如下:

 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)