2017-01-23 72 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有点生锈:) –