2010-09-15 94 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) 
    
    相關問題