2017-01-23 75 views
1

我正在閱讀編碼爲UTF-8.csv。 我想創建一個索引並重寫csv。 索引創建爲一個正在進行的數字單詞的第一個字母。 Python 2.7.10,Ubuntu服務器UTF-8編碼/解碼的問題

#!/usr/bin/env python 
# -*- coding: utf-8 -*- 
counter = 0 
tempDict = {} 
with open(modifiedFile, "wb") as newFile: 
    with open(originalFile, "r") as file: 
     for row in file: 
      myList = row.split(",") 
      toId = str(myList[0]) 

      if toId not in tempDict: 
       tempDict[toId] = counter 
       myId = str(toId[0]) + str(counter) 
       myList.append(myId) 
       counter += 1 
      else: 
       myId = str(toId[0]) + str(tempDict[toId]) 
       myList.append(myId) 

      # and then I write everything into the csv 
      for i, j in enumerate(myList): 
       if i < 6: 
        newFile.write(str(j).strip()) 
        newFile.write(",") 

       else: 
        newFile.write(str(j).strip()) 
        newFile.write("\n") 

問題是以下內容。 當一個單詞以一個奇特的字母開頭,如

  • Č
  • É
  • Â轉
  • ...

我開始創建一個?的ID,但不與字的字母。 奇怪的部分是,與我創建的csv一樣,帶有花哨字母的單詞被寫入正確。沒有?或其他表示錯誤編碼的符號。

這是爲什麼?

+1

你使用的是什麼版本的Python? –

+0

如果你在Windows上,它可能使用語言環境編碼。 –

+0

@TimMartin 2.7.10,在Ubuntu服務器上工作 – Stophface

回答

0

在python 2.x字符串默認情況下是非unicode - str()返回一個非unicode字符串。改爲使用unicode()

此外,你必須通過codecs.open()打開使用utf-8編碼的文件,而不是內置open()

+0

嗯,但爲什麼其他單詞編碼正確?升級到python 3.x會解決這個問題嗎? – Stophface

+0

@Stophface *爲什麼其他單詞編碼正確*在'toId''發生了以多字節字符開頭的情況時,實際上只是第一個字節,因此它不再是有效字符。你處理的其他人只是簡單地複製輸入數據(用逗號分割不會引入任何問題)。 – Leon

+0

@Stophface *是否會升級到python 3.x解決這個問題*是 – Leon

3

絕對不應該在學習Python 2,除非您需要一個specific傳統C擴展。

Python 3對unicode/bytes處理進行了重大更改,它可以刪除(大部分)隱式行爲並使錯誤可見。由於默認編碼是依賴於環境和平臺的,因此使用open('filename', encoding='utf-8')仍然是一個好習慣。

事實上,在Python 3中運行你的程序應該修改它,不作任何改變。但是,這裏的地方你的錯誤在於:

 toId = str(myList[0]) 

這是一個空操作,因爲myList[0]已經是一個str

  myId = str(toId[0]) + str(counter) 

這是一個錯誤:含有UTF-8數據toIdstr(字節字符串)。除了一次只處理一個字符以外,您從未想過要使用UTF-8數據做任何事情。

with open(originalFile, "r") as file: 

這是一種樣式錯誤,因爲它掩蓋了內置函數file

有兩個變化,使這個運行Python 2.下

  1. 變化open(filename, mode)io.open(filename, mode, encoding='utf-8')
  2. 停止對字符串調用str(),因爲它實際上試圖對它們進行編碼(使用ASCII!)。

但你真的應該切換到Python 3

有新的2.6和2.7的幾件是旨在縮小差距爲3,其中之一是io模塊,其行爲在所有新的好方法中:Unicode文件和通用換行符。

~$ python2.7 -c 'import io,sys;print(list(io.open(sys.argv[1],encoding="u8")))' <(printf $'\xc3\x84\r\n\xc3\xb9\r\n') 
[u'\xc4\n', u'\xf9\n'] 
~$ python3 -c 'import sys;print(list(open(sys.argv[1],encoding="u8")))' <(printf $'\xc3\x84\r\n\xc3\xb9\r\n') 
['Ä\n', 'ù\n'] 

這可能是有用編寫兩個2和3軟件同樣,編碼參數是可選的,但在所有平臺上的默認編碼是環境相關的,所以這是很好的是具體的。

+1

在Python 2中,您應該使用'更緊密地匹配Py3'open()'的io.open()'並給出適當的通用行支持 –

+1

謝謝,我的2to3有點生鏽:) –