【问题标题】:Python reading csv problem : extra whitespacePython读取csv问题:额外的空格
【发布时间】:2011-03-21 02:18:14
【问题描述】:

当我试图解析一个由 MS SQL 2005 express edition 的查询导出的 csv 时,python 给我的字符串完全出乎我的意料。例如,如果 csv 文件中的行是:" aaa,bbb,ccc,dddd",然后当 python 将其解析为字符串时,它变成:" a a a a , b b b , c c c, d d d d" 类似的东西.....会发生什么???
我试图删除代码中的空格但不起作用。

import os
import random


f1 = open('a.txt', 'r')
f2 = open('dec_sql.txt', 'w')
text = 'abc'

while(text  != ''):

    text = f1.readline()
    if(text==''):
        break

    splited = text.split(',')
    for i in range (0, 32):
        splited[i] = splited[i].replace(' ', '')

    sql = 'insert into dbo.INBOUND_RATED_DEC2010 values ('
    sql += '\'' + splited[0] + '\', '
    sql += '\'' + splited[1] + '\', '
    sql += '\'' + splited[2] + '\', '
    sql += '\'' + splited[3] + '\', '
    sql += '\'' + splited[4] + '\', '
    sql += '\'' + splited[5] + '\', '
    sql += '\'' + splited[6] + '\', '
    sql += '\'' + splited[7] + '\', '
    sql += '\'' + splited[8] + '\', '
    sql += '\'' + splited[9] + '\', '
    sql += '\'' + splited[10] + '\', '
    sql += '\'' + splited[11] + '\', '
    sql += '\'' + splited[12] + '\', '
    sql += '\'' + splited[13] + '\', '
    sql += '\'' + splited[14] + '\', '
    sql += '\'' + splited[15] + '\', '
    sql += '\'' + splited[16] + '\', '
    sql += '\'' + splited[17] + '\', '
    sql += '\'' + splited[18] + '\', '
    sql += '\'' + splited[19] + '\', '
    sql += '\'' + splited[20] + '\', '
    sql += '\'' + splited[21] + '\', '
    sql += '\'' + splited[22] + '\', '
    sql += '\'' + splited[23] + '\', '
    sql += '\'' + splited[24] + '\', '
    sql += '\'' + splited[25] + '\', '
    sql += '\'' + splited[26] + '\', '
    sql += '\'' + splited[27] + '\', '
    sql += '\'' + splited[28] + '\', '
    sql += '\'' + splited[29] + '\', '
    sql += '\'' + splited[30] + '\', '
    sql += '\'' + splited[31] + '\', '
    sql += '\'' + splited[32] + '\' '

    sql += ')'

    print sql
    f2.write(sql+'\n')


f2.close()
f1.close()

【问题讨论】:

  • 您可以发布输入文件吗?这将使诊断更容易。
  • 问题已解决。该文件是一个 unicode 文件。我使用 Ultraedit 将其转换为 ascii 文件,然后 python 再次工作。谢谢大家。
  • 如果您确定哪些字符被拒绝,您可以在我的代码示例中添加到 ENCODING_REGEX_REPLACEMENT_LIST 并跳过 Ultraedit 步骤。

标签: python csv


【解决方案1】:

在我看来,MS SQL 2005 查询的输出是一个 unicode 文件。 python csv module 无法处理 unicode 文件,但在 csv 模块的文档中有一些 sample code 描述了如何解决该问题。

另外,一些文本编辑器允许您使用不同的编码保存文件。例如,我在 Notepad++ 中打开了 MS SQL 2005 查询的结果,它告诉我文件是 UCS-2 编码的,我可以从编码菜单将它转换为 UTF-8。

【讨论】:

  • 这就是微软所说的“unicode”文件。它实际上是 UTF-16(LE)。
【解决方案2】:

尝试在记事本中打开文件并使用全部替换功能将' '替换为''

【讨论】:

    【解决方案3】:

    您的文件很可能使用 2 字节字符编码进行编码 - 很可能是 utf-16(但也可能是其他编码。

    要让 CSV 正确读取它,您可以使用编解码器打开它,以便将其解码为读取的内容 - 这样做您的 python 程序中有 Unicode 对象(而不是字符串对象)。

    所以,不要用

    打开文件
    my_file = open ("data.dat", "rt")
    

    使用: 导入编解码器

    my_file = codecs.open("data.dat", "rt", "utf-16") 
    

    然后将其提供给 CSV 模块,其中:

    导入 csv 阅读器 = csv.reader(my_file) first_line = 假 对于阅读器中的行: if first_line: #跳过标题行 first_line = 真 继续 #组装sql查询并发出

    另一件事是,将您的“查询”构造成 32 行重复代码是编程时的一件好事。即使在缺乏丰富的字符串处理工具的语言中,也有更好的方法来做到这一点,但在 Python 中,您可以简单地这样做:

    sql = 'insert into dbo.INBOUND_RATED_DEC2010 values (%s);' % ", ".join("'%s'" % value for value in splited )
    

    而不是那些 33 行组装您的查询。 (我告诉它在里面插入一个字符串 第一个字符串上的括号。在%operator 之后,字符串“,” 与“join”方法一起使用,以便将作为参数传递给join 的序列上的所有元素粘贴在一起。这个序列由一个字符串组成,包含一个包含在单引号内的值,用于拆分数组中的每个值。

    【讨论】:

    • 附言。没有像其他答案暗示的“unicode文件”之类的东西。有几种不同的编码,每一种都能够表示 unicode 字符表的不同子集。
    • -1 你不能输入 unicode 或 UTF-16;您需要将其从 UTF-16 重新编码为 UTF-8 并将其提供给 csv 阅读器。请参阅 (2.x) csv 模块手册中的示例。
    • ... 和 UTF-8、UTF-16、UTF-32 和 GB18030 可以表示 ALL 2**21(大约)Unicode 代码点。
    【解决方案4】:

    使用 Python 内置的 CSV 阅读器可能会有所帮助。看起来像是 unicode 的问题,这个问题让我很沮丧。

    import tkFileDialog
    import csv
    
    ENCODING_REGEX_REPLACEMENT_LIST = [(re.compile('\xe2\x80\x99'), "'"),
                                       (re.compile('\xe2\x80\x94'), "--"),
                                       (re.compile('\xe2\x80\x9c'), '"'),
                                       (re.compile('\xe2\x80\x9d'), '"'),
                                       (re.compile('\xe2\x80\xa6'), '...')]
    
    def correct_encoding(csv_row):
        for key in csv_row.keys():
            # if there is a value for the current key
            if csv_row[key]:
                try:
                    csv_row[key] = unicode(csv_row[key], errors='strict')
                except ValueError:
                    # we have a bad encoding, try iterating through all the known
                    # bad encodings in the ENCODING_REGEX_REPLACEMENT and replace
                    # everything and then try again
                    for (regex, replacement) in ENCODING_REGEX_REPLACEMENT_LIST:
                        csv_row[key] = regex.sub(replacement,csv_row[key])
                    print(csv_row)
                    csv_row[key] = unicode(csv_row[key])
            # if there is NOT a value for the current key
            else:
                csv_row[key] = unicode('')
        return csv_row
    
    filename = tkFileDialog.askopenfilename()
    csv_reader = csv.DictReader(open(filename, "rb"), dialect='excel') # assuming similar dialect
    for csv_row in csv_reader:
        csv_row = correct_encoding(csv_row)
        # your application logic here
    

    【讨论】:

    • 哇,哪个勇敢的人贬低了我,没有留下任何解释。
    • 是我。你的代码写得很好,可以猜测编码并清除地毯下的错误。正如 srgerg 的回答中所引用的,正确的方法是了解您的编码并处理它。 OP 在接受您的回答方面服务不佳。
    • 我发布的代码解释了如何解决这个问题。虽然它并不完美,但它是一个可以在现实世界中修改和使用的具体解决方案(不是您想要的学术答案)。如果您对哪个答案被接受有疑问,那么您应该减少问题而不是答案。
    • -1 仅用于使用正则表达式将 UTF-8 编码字节更改为 ASCII。
    • @pokstad:用 ASCII 替换 UTF-8 编码的字节是 -1,无论你是使用 re.sub 还是 str.replace 还是运行 awk 的子进程 - 罪是用 UTF-8 编码的字节做任何事情,而不是解码它们。
    猜你喜欢
    • 1970-01-01
    • 2018-11-05
    • 1970-01-01
    • 2014-07-30
    • 2016-05-22
    • 1970-01-01
    • 2018-11-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多