Python在utf-8或cp1252中导入.csv文件

时间:2018-10-09 01:42:09

标签: python python-3.x csv file-io utf-8

前段时间,我问question有关处理带有特殊字符的.csv文件的问题。当时我有兴趣解决90%的案件,但现在我又回到了最后的10%。

与以前的设置基本相同:

  1. 许多输入文件
  2. 所有.csv
  3. 新功能:现在,我想在某些输入中保留特殊字符。但是,我无法控制所有输入文件的格式,因此我需要处理一些混合文件。我试图解决该问题的方法是,当我想使用其他编码格式时,传递一个关键字参数。

代码如下:

Select(Function(c) ChechBoxesText(Convert.ToInt32(c.Tag))))

以上结果是,如果我通过本机编解码器传递另存为.CSV的Excel文件,则导入有效。但是,调用包含formatting ='utf-8'关键字arg的unicodecsv文件崩溃

该错误消息表明我沿线某处传递了错误类型的对象。这是我第一次尝试从UTF-8文件中读取一行时发生的情况

import csv
import unicodecsv
#<Lots of other declarations and initialization>

def _csv_dict(self, file,index_field, ScrubMe, **kwargs):

#some irrelevant initialization stuff here.

    if 'formatting' in kwargs:
        formatting = kwargs['formatting']
    else:
        formatting =  None #cp1252 is OS default

    with open(file, encoding=formatting, errors='ignore') as f: #newline = '',
        if formatting == None:
            reader = csv.DictReader(f, dialect = 'excel')
        else: #assume for now UTF-8 is the only other supported format
            reader = unicodecsv.DictReader(f, dialect = csv.excel)

        for line in reader:
            <do some stuff - it's mostly building dictionaries, but I
generally edit the data to only keep the stuff I care about and do a little
data transformation to standard formats >

根据我的阅读,UTF-8实际上是制表符分隔而不是逗号分隔,但是我“认为”它应该以相同的方式工作。

我觉得我可能已经弄糟了一些非常简单的东西,但是我花了很多时间寻找寻求帮助的合适方法。预先感谢您的任何建议。

1 个答案:

答案 0 :(得分:0)

我要替换最初的答案,因为我正在进行很多事情,并且花了一段时间才将它们解开。

1)@lenz是正确的。在Python 3中,无需使用unicodecsv.DictReader。令我感到困惑的部分是实现上的差异。

a)对于来自Python 2的旧版unicodecsv.DictReader:

kw_args={'errors' : None}
with open(filename, 'rb', **kw_args) as file:
    reader = unicodecsv.DictReader(file, dialect = csv.excel, encoding='utf_8_sig' )

b)对于Python 3 csv.DictReader

kw_args={'newline' : '','errors' : None,'encoding' : 'utf_8_sig'}
with open(filename, 'r', **kw_args) as file:
    reader = csv.DictReader(file, dialect = csv.excel )

总结差异

  • 打开文件的模式现在是文本而不是字节
  • 由于打开方法不同,因此可以(应该)在DictReader中打开文件,而应该在DictReader中指定编解码器。
  • newline参数仅对以文本形式打开的文件有效。

2)因为我的UTF-8文件是Excel生成的,所以文件顶部具有utf_16_le样式的BOM。唯一适用于此的编码是“ utf_8_sig”。

3)因为我的输出文件被SQL Server下游读取,所以输出编解码器需要为“ utf_16_le”,否则SQL Server无法识别它。

4)另外,由于目标是SQL Server,因此我必须手动将BOM表插入文件顶部。

csvfile.write('\uFEFF') 
writer.writeheader()

如果您在Excel中打开上述输出文件,它将不再位于列中,但是SQL Server(实际上是SSIS)现在知道如何读取该文件。

5)只是想和我多一点,有人在一些记录中有“ \ n”。使用Excel作为源和目标,这不是问题,但这是SSIS的问题。我的解决方案:

for r in record_list:
    temp={}
    for k,v in r.items():

        if isinstance(v,str):
            temp[k] = v.replace('\n',' ')
        else:
            temp[k] = v
    writer.writerow(temp)