woo*_*oot 2 python csv io optimization
给定10个1MB csv文件,每个文件的布局略有不同,我需要将它们组合成具有相同标题的规范化单个文件.空字符串适用于空值.
列的示例:
1. FIELD1, FIELD2, FIELD3
2. FIELD2, FIELD1, FIELD3
3. FIELD1, FIELD3, FIELD4
4. FIELD3, FIELD4, FIELD5, FIELD6
5. FIELD2
Run Code Online (Sandbox Code Playgroud)
输出看起来像(虽然顺序不重要,我的代码将它们按顺序发现):
FIELD1, FIELD2, FIELD3, FIELD4, FIELD5, FIELD6
Run Code Online (Sandbox Code Playgroud)
所以基本上字段可以以任何顺序出现,字段可能丢失,或者之前看不到的新字段.所有必须包含在输出文件中.不需要连接,最后部件中的数据行数必须等于输出中的行数.
将所有10MB读入内存即可.以某种方式使用100MB来做它不会.如果需要,您可以一次打开所有文件.大量的文件,可用的内存,但它将针对NAS运行,因此它需要高效(不是太多的NAS操作).
我现在的方法是将每个文件读入列列表,在发现新列时构建新列列表,然后将其全部写入单个文件.我希望有人有一些更聪明的东西,因为我是这个过程的瓶颈,所以任何缓解都是有帮助的.
如果有人想尝试,我在这里有样品文件.我将发布当前代码作为可能的答案.寻找使用本地磁盘在我的服务器(大量内核,大量内存)上运行它的最快时间.
使用csv.DictReader()
和csv.DictWriter()
对象的两遍方法.通过一个收集所有文件中使用的标头集,然后根据标头传递两个然后复制数据.
收集标题就像访问fieldnames
reader对象上的属性就足够了:
import csv
import glob
files = []
readers = []
fields = set()
try:
for filename in glob.glob('in*.csv'):
try:
fileobj = open(filename, 'rb')
except IOError:
print "Failed to open {}".format(filename)
continue
files.append(fileobj) # for later closing
reader = csv.DictReader(fileobj)
fields.update(reader.fieldnames) # reads the first row
readers.append(reader)
with open('result.csv', 'wb') as outf:
writer = csv.DictWriter(outf, fieldnames=sorted(fields))
writer.writeheader()
for reader in readers:
# copy across rows; missing fields will be left blank
for row in reader:
writer.writerow(row)
finally:
# close out open file objects
for fileobj in files:
fileobj.close()
Run Code Online (Sandbox Code Playgroud)
每个阅读器都会生成一个包含所有字段子集的字典,但DictWriter
会使用restval
参数的值(默认为''
省略时,就像我在这里所做的那样)来填充每个缺失键的值.
我在这里假设Python 2; 如果这是Python 3,您可以使用a ExitStack()
来管理读者的打开文件; 省略b
文件模式并newline=''
为所有打开的调用添加一个参数,以便将新行处理留给CSV模块.
上面的代码只使用缓冲区来读写行; 行一次一次一行地从一个打开的阅读器移动到一个写入器.
不幸的是,我们无法使用,writer.writerows(reader)
因为DictWriter.writerows()
实现首先将所有内容转换reader
为列表列表,然后再将其传递给基础csv.writer.writerows()
方法,请参阅Python错误跟踪器中的问题23495.
归档时间: |
|
查看次数: |
1135 次 |
最近记录: |