2013-07-09 40 views
0

我有一個使用xlwt/xlrd來處理excel文件的python腳本。在我的腳本的開始,我有以下代碼:在Python中正確解碼unicode時遇到問題

#if you got a csv in parameters, convert it to an xls file 
if '.csv' in sys.argv[1]: 
    #name of new file after conversion is finished 
    name = sys.argv[1] 
    csvfile = open(sys.argv[1], 'rb') 
    try: 
     #extract data from .csv 
     csvReader = csv.reader(csvfile, delimiter=' ', quotechar='|') 
     csvData = list(csv.reader(open(name, 'rb'))) 
     # write to a xls file 
     outFile = xlwt.Wrokbook() 
     newSheet = outFile.add_sheet('Sheet 1') 
     # traverse over 2d array to write each individual cell 
     for row in range(len(csvData)): 
      for col in range(len(csvData[0])): 
       newSheet.write(row, col, csvData[row][col].encode('utf8')) 
     name = name[:-4] + ".xls" #change extension of file 
     outFile.save(name) 
     wb = open_workbook(name) 
    finally: 
     csvfile.close() 

這給行outFile.save(名)錯誤

UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 44: ordinal not in range(128) 

我有唯一有用的東西發現到目前爲止,以幫助這是UnicodeDecodeError: 'ascii' codec can't decode byte 0xef in position 1,但我的終端使用utf8作爲其編碼。

編輯: 完全忘了提這個,很抱歉。

我相信帶有.encode的行會以某種方式引起錯誤,但我無法想象如何。我原本沒有.encode,然後我添加了.encode('utf8'),也嘗試過.encode('utf-8')和unicode(字符串'utf8')。我不知道還有什麼可以嘗試解決這個問題。編號: 我試過Brian的建議沒有用。此外,我嘗試了codecs.open建議,並嘗試在創建工作簿時指定編碼。這些事情都沒有改變錯誤。我試過的唯一一個改變錯誤的地方就是在newSheet.write中添加了.encode。沒有它,我得到:

UnicodeEncodeError: 'ascii' codec can't encode character u'\u2013' in position 44: ordinal no in range(128) 

而且用它我得到:

UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 44: ordinal not in range(128) 
+0

'csvData [行] [COL] .decode( 'utf-8')'也許?假設是拋出錯誤的那一行 –

+0

什麼版本的python? – Brian

+0

@Brian Python 2.7 – avorum

回答

1

按照docs

csv模塊不支持直接讀寫Unicode的, 但它是8位清除保存ASCII字符的NUL 字符的一些問題。因此,只要避免使用NUL的編碼,如 UTF-16,就可以編寫處理 編碼和解碼的函數或類。建議使用UTF-8。

請嘗試下面的代碼片段,它爲您提供了一個使用unicode數據讀取csv的生成器。請注意,此代碼直接取自上面鏈接的文檔:

import csv 

def unicode_csv_reader(unicode_csv_data, dialect=csv.excel, **kwargs): 
    # csv.py doesn't do Unicode; encode temporarily as UTF-8: 
    csv_reader = csv.reader(utf_8_encoder(unicode_csv_data), 
          dialect=dialect, **kwargs) 
    for row in csv_reader: 
     # decode UTF-8 back to Unicode, cell by cell: 
     yield [unicode(cell, 'utf-8') for cell in row] 

def utf_8_encoder(unicode_csv_data): 
    for line in unicode_csv_data: 
     yield line.encode('utf-8') 

作爲如何使用上面的代碼的一個例子,而不是

csvReader = csv.reader(csvfile, delimiter=' ', quotechar='|') 

使用

csvReader = unicode_csv_reader(csvfile, delimiter=' ', quotechar='|') 

yield是發電機功能的返回等價物。該函數返回一個生成器對象,這是一種Python中可迭代的類型。 **kwargs代表關鍵字參數,這是您在寫入時實際傳遞的內容delimiter=' ', quotechar='|'

+0

我認爲這是錯的 - 示例生成器適用於CSV數據本身是Python unicode對象的情況,而不是使用utf-8編碼的字符串。因此輸入「unicode_csv_data」的編碼。如果文件是用'codecs.open'打開的,並且因此在迭代時返回Unicode對象,它可能會工作,但我想仔細測試。 –

+0

感謝您的幫助! – avorum

+0

我試過了(以及迄​​今爲止給出的所有其他建議),而且我仍然遇到同樣的錯誤。任何其他想法? – avorum

0

問題是,如果輸入中包含非ascii字符,則不會將它們傳遞給xlwt,而是處於期望的狀態。

根據xlwt的文檔:

的unicode實例寫成的。使用在創建Workbook實例時指定的編碼(默認值:'ascii')將str實例轉換爲unicode。

https://secure.simplistix.co.uk/svn/xlwt/trunk/xlwt/doc/xlwt.html?p=4966#xlwt.Worksheet.write-method

也就是說,當你輸入CSV文件包含使用編碼的非ASCII字符的UTF-8,讀者拉它作爲編碼的Python字符串 - 如果你直接您會看到它看到多個十六進制字節,例如'\xc3\xa1'對於小寫字母a-acute。當你將它寫入工作表時,它必須對其進行解碼。在創建工作簿時,您沒有指定編碼,因此它嘗試使用默認的ascii編碼來執行此操作。正如你所看到的,這不起作用,因爲這些不是ASCII字節。

您的選擇是將Unicode字符串傳遞給工作表,將它們從csv閱讀器的結果中解碼出來(或將csv閱讀器包裝成解碼所有內容的東西 - 這是同樣的事情),或者在工作簿上設置編碼時創造它。

0

嘗試使用內置的編解碼器庫打開文件:

#!/usr/bin/env python2.7 
# -*- coding: UTF-8 -*- 
import codecs 

with codecs.open(sys.argv[1], "rb", encoding="utf-8") as csvfile: 
    csvReader = csv.reader(csvfile, delimiter=' ', quotechar='|') 
    # snipped the rest of the code