字符串或文件的分隔符:使用csv.reader()而非csv.Sniffer()
背景:我在从亚马逊的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()
处理。