2010-09-15 98 views
36

当上传非ASCII字符的文件,我得到UnicodeEncodeError:UnicodeEncodeError: 'ASCII' 编解码器不能编码字符

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) 
+0

您还可以提供模型/字段定义吗?特别是我对看到'upload_to'定义感兴趣。 – 2010-09-15 14:21:13

+0

已更新为upload_to定义。 – vorpyg 2010-09-16 12:13:24

+2

对于任何仍然在这里登陆的人来说,检查Django票据最后由akaihola发表的评论,他说:“Debian默认使用LANG = C语言环境运行Apache,至少在使用mod_wsgi运行时,它会在其名称中加载带有特殊字符的文件。/etc/apache2/envvars中的UTF-8语言环境应该解决此问题“票证:http://code.djangoproject.com/ticket/6009 – 2011-06-21 13:34:52

回答

12

问题调查这个多一些,我发现,我还没有设置字符集在我的主要Nginx的后配置文件:

http { 
    charset utf-8; 
} 

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

+4

这只有在nginx直接运行后端代码的情况下才能起作用。假设它是gunicorn或uwsgi之类的代理,那么必须将wsgi服务器的环境配置为使用UTF-8。将此添加到您的Nginx配置中并不会造成影响,但它可能无法解决您的问题。 – amjoconn 2012-07-16 18:04:26

+0

正如@amjoconn所提到的,在我的情况下,通过在我的uwsgi-config文件中添加“env = LC_ALL = ru_RU.UTF-8”来解决问题 – 2014-08-13 12:20:12

4

很难没有看到一点点更多的代码说,但它看起来与此有关的问题: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

+0

我怀疑这可能与此有关。我试着在字符串前添加一个u,如下所述:http://stackoverflow.com/questions/2457087/unicodedecodeerror-on-attempt-to-save-file-through-django-default-filebased-backe/2458200 #2458200没有运气。你有链接到nginx修复? – vorpyg 2010-09-16 12:18:35

+1

查看我最新的链接编辑。 – 2010-09-16 13:46:08

+0

谢谢,仍然没有工作,但。我已经尝试设置区域设置,如Django文档中所示,并尝试将charset utf8添加到我的nginx配置中。也许我只需要重写保存方法来首先重命名文件... – vorpyg 2010-09-16 19:32:38

24

在必须在只接受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字符的实体标题的文件。

+0

谢谢!在无果寻找一个简单的问题后,我偶然发现了这个答案:我如何在Python中发送一个包含非拉丁字符的电子邮件?您的解决方案有效 – skanatek 2013-03-26 20:30:07

+0

print unicode(exc).encode('ascii','ignore') – 2015-09-24 22:44:01

12

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

执行manage.py之前,运行脚本设置

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

解决了与上传文件名

4

如前所述,它与语言环境有关。例如,如果您使用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 

此外,您还可以检查你的locale在您的模板,在视图中使用此:

import locale 
data_to_tpl = {'loc': locale.getlocale(), 'lod_def': locale.getdefaultlocale()} 

而就在您的模板中显示{{loc}} - {{loc_def}}

您将获得关于您的语言环境设置的更多信息!这对我来说非常有用。

37

对于任何遇到此问题的人,在运行Django时使用Supervisor,解决方案是添加例如以下为超级的配置的supervisord部分:

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

这解决了这个问题,我在监3.0a8在Debian挤压运行。

+5

确保你的/etc/init.d/supervisor停止并且/ etc启动/init.d/supervisor以使更改生效。重新启动不起作用。 – amjoconn 2012-07-16 13:32:20

+0

如果您遇到此错误_Usepected key/value pairs_结束,您将需要引用这些值。例如环境= LANG = 'en_US.utf8'。 https://lists.supervisord.org/pipermail/supervisor-users/2010-March/000539.html – amos 2013-11-15 09:43:44

+1

你可以用'supervisorctl reread'和'supervisorctl restart myservice'强制读取配置文件,而不是停止并启动整个守护进程。 – Udi 2014-05-13 08:39:29

3

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

from __future__ import unicode_literals 

,并使用force_text()

from django.utils.encoding import force_text 
4

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

如果您使用virtualenv可以更改(或创建如果它不存在)env/lib/python2.7/sitecustomize.py并添加:

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

或者,如果你是在生产系统中,你可以做同样的/usr/lib/python2.7/sitecustomize.py

9

akaihola的回答很有帮助。对于那些谁运行Django应用程序与uWSGI通过新贵脚本管理,只是这些行添加到您的/etc/init/yourapp.conf

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

它解决了这个问题对我来说。

+2

谢谢!这是解决我的问题的方式! 'env LANG =“en_US.UTF-8”env LC_LALL =“en_US.UTF-8” env LC_LANG =“en_US.UTF-8”'。请注意,它是'env'而不是'export'。这是在System V脚本(/etc/init/xxx.conf)下使用的语法。这个错误花了我几个小时。 – moonkey 2015-06-17 05:02:46

1

就从这个线程和其他人的答案建设中...

我有尝试上传的文件名以非ASCII字符时genericpath.py给人一种UnicodeEncodeError同样的问题。

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

一切都在本地,但没有工作正常的服务器上

下面是我 1.加入/etc/nginx/nginx.conf(没有解决这个问题)

http { 
    charset utf-8; 
} 
步骤
  • 我加入此行等/默认/区域(没有解决该问题)
  • 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皇帝/诸候/我的站点,配置-INI文件

    env = LANG=en_US.utf8 
    
    +0

    我更新的解决方案在这里:http://stackoverflow.com/a/31001281/3003438 – 2017-04-21 06:58:01

    0

    没有为我工作(使用Apache在Ubuntu和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) 
    
    相关问题