字符串或文件的分隔符:使用csv.reader()而非csv.Sniffer()

0 投票
1 回答
620 浏览
提问于 2025-04-18 18:47

背景:我在从亚马逊的S3上流式读取日志文件。经过几步处理后,我从压缩文件中得到了一个类似文件的对象。对于gzipped文件,我会在流中解压一部分,这部分是一个字符串,然后用str.splitlines()把它分成一行一行的列表。

csv.reader可以接受任何有迭代器协议的东西,比如文件和列表。不过,对于文件来说,处理完后我需要用file.close()来关闭它们。解压和解压缩后的文件变成了csv和tsv文件,也就是用逗号或制表符分隔的文件。

delims = [',','\t']

对于zip文件,因为中间步骤生成的ZipExtFile没有seek()这个功能,所以我不能使用csv.Sniffer。而对于gzip文件,它们是流式读取的,变成了一行一行的列表。

我该如何动态地确定在调用csv.reader时使用哪个分隔符呢?我现在使用下面的代码(基于这个)。理想情况下,我会把一个teststr传给这个,然后调用csv.reader(csvfile, delimiter = k)

但是,我该如何获取文件或列表的一个样本来测试,然后再返回到文件的开头,因为这两种输入都没有seek()这个功能呢?

teststr = 'how,-do,-you,-dynamically,-identify,-unknown,-delimiters,-in,-a,-data'

def find_delimiter(teststr):
    # how-do-you-dynamically-identify-unknown-delimiters-in-a-data-file
    possible = [',','\t','-']
    count = {}

    for c in teststr:
        if c in possible: count[c] = count.get(c,0) + 1

    delim = [key for key,val in count.iteritems() if val == max(count.values())]

    if len(delim) == 1: 
        delim = delim[0]
    else:
        print delim
        delim = None
    return delim

k = find_delimiter(teststr)
print k

1 个回答

0

个人解决方案的总结。

我决定这个小方法可行,所以我换了个思路:我打开文件或者流式读取文件,暂时不使用 csv.reader()(希望大部分数据在换行符的处理上是正常的,这应该没问题),我用字符串的 .readline() 方法来抓取几行内容。

然后把这些内容发送到上面的 find_delimiter 方法,接着把这些行和返回的分隔符一起传给 csv.reader() 处理。

撰写回答