2010-10-14 97 views
5

我正在使用Django應用程序將字符串導出到CSV文件。該字符串是通過前端表單提交的消息。但是,當輸入中提供了一個unicode單引號時,我得到了這個錯誤。Python Unicode CSV導出(使用Django)

UnicodeEncodeError: 'ascii' codec can't encode character u'\u2019' 
    in position 200: ordinal not in range(128) 

我一直在嘗試使用下面的代碼將unicode轉換爲ascii,但仍然得到類似的錯誤。

UnicodeEncodeError: 'ascii' codec can't encode characters in 
position 0-9: ordinal not in range(128) 

我已經通過幾十個網站篩選和學到了很多關於unicode的,但是,我還是沒能這個unicode轉換爲ASCII。我不在乎算法是否刪除了unicode字符。註釋行表示我嘗試過的一些不同的選項,但錯誤仍然存​​在。

import csv 
import unicodedata 

... 

#message = unicode(unicodedata.normalize(
#       'NFKD',contact.message).encode('ascii','ignore')) 
#dmessage = (contact.message).encode('utf-8','ignore') 
#dmessage = contact.message.decode("utf-8") 
#dmessage = "%s" % dmessage 
dmessage = contact.message 

csv_writer.writerow([ 
     dmessage, 
]) 

有沒有人有任何建議去除unicode字符,我可以將它們導出到CSV?這個看似簡單的問題讓我頭暈目眩。任何幫助深表感謝。 謝謝, 喬

+0

感謝修復格倫 – 2010-10-14 01:44:53

回答

7

您不能將Unicode字符u'\u2019'(U + 2019右單引號)編碼爲ASCII,因爲ASCII中沒有該字符。 ASCII只是基本的拉丁字母,數字和標點符號;你不會得到任何重音字母或像這個角色的「聰明引號」。所以你將不得不選擇另一種編碼。現在通常情況下要做的事情就是導出爲UTF-8,UTF-8可以存放任何Unicode字符。不幸的是,如果你的目標用戶正在使用Office(他們可能是),他們將無法讀取CSV中的UTF-8編碼字符。相反,Excel將使用該機器的系統默認代碼頁(也誤導性地稱爲'ANSI'代碼頁)讀取文件,並且最終得到類似’的mojibake而不是

因此,這意味着如果您希望字符正確顯示,您必須猜測用戶的系統默認代碼頁。對於西方用戶,這將是代碼頁1252.與非西方Windows安裝的用戶將看到錯誤的字符,但是你沒有辦法做到這一點(除了組織一封信寫作活動給微軟放棄愚蠢的廢話ANSI已經和其他人一樣使用UTF-8)。

代碼頁1252可以包含U + 2019(),但顯然還有更多的字符無法表示。爲避免爲這些字符獲取UnicodeEncodeError,可以使用ignore參數(或replace用問號替換它們)。

dmessage= contact.message.encode('cp1252', 'ignore') 

或者,放棄和刪除所有非ASCII字符,這樣不管每個人都得到現場的同樣糟糕的經歷:

dmessage= contact.message.encode('ascii', 'ignore') 
+1

@bobince:「猜測用戶的系統默認代碼頁」......您嘗試使用locale.getpreferredencoding()或locale.getdefaultlocale()[1]'來獲得權威性的問題? – 2010-10-14 02:35:03

+2

@John:我在想Django是否參與了我們正在討論的服務器端應用程序,並且不能保證服務器的默認編碼與客戶端類似。 (在客戶端是Windows而服務器不是的情況下,編碼永遠不會匹配。) – bobince 2010-10-14 02:42:56

+1

@bobince:儘管這個問題沒有被指定使用;對於我們所知的所有csv文件可能只是爲了持久性目的,並且只能在內部使用。 – 2010-10-14 03:01:15

2

編碼是一種痛苦,但如果你在Django工作你試過從django.utils.encodingsmart_unicode(str)?我發現通常會這樣做。

我發現的唯一的其他選擇是對字符串使用內置的python encode()decode(),但是您必須爲這些指定編碼,說實話,這很痛苦。

+0

謝謝,沃夫悖論,我給了smart_unicode一個鏡頭,讓你知道如何繼續下去。 – 2010-10-14 01:38:43

1

[忠告:我不是一個djangoist ; Django可能有更好的解決方案]。

一般非Django的具體回答:

如果你有知非ASCII字符一個很小的數目,並有用戶可接受的ASCII等價物對他們來說,你可以建立一個轉換表,並使用unicode.translate方法:

smashcii = { 
    0x2019 : u"'", 
    # etc 
    # 

smashed = input_string.translate(smashcii) 
+0

我必須給這個方法一個鏡頭。至少可以讓我通過這個問題。謝謝你的建議。 – 2010-10-14 15:58:54