我有一个25GB的文件需要处理。以下是我目前正在做的事情,但打开需要非常长的时间:
collection_pricing = os.path.join(pricing_directory, 'collection_price')
with open(collection_pricing, 'r') as f:
collection_contents = f.readlines()
length_of_file = len(collection_contents)
for num, line in enumerate(collection_contents):
print '%s / %s' % (num+1, length_of_file)
cursor.execute(...)
我该如何改进?
-
除非文件中的行真的很大,否则不要在每一行都打印进度。打印到终端的速度非常慢。打印进度,例如每100行或每1000行。
-
使用可用的操作系统工具来获取文件的大小-
os.path.getsize()
,请参阅在Python中获取文件大小? -
去掉
readlines()
以避免向内存中读取25GB。相反,逐行读取和处理,请参阅例如如何在python 中逐行读取大文件
将文件传递两次:一次用于计数行,一次用于打印。永远不要对这么大的文件调用readlines
——您最终会将所有内容都交换到磁盘上。(实际上,一般情况下永远不要调用readlines
。这很傻。)
(顺便说一句,我假设你实际上是在使用行数,而不仅仅是行数——你在那里发布的代码实际上除了文件中的换行数之外,没有使用文件中的任何内容。)
结合上面的答案,下面是我如何修改它的。
size_of_file = os.path.getsize(collection_pricing)
progress = 0
line_count = 0
with open(collection_pricing, 'r') as f:
for line in f:
line_count += 1
progress += len(line)
if line_count % 10000 == 0:
print '%s / %s' % (progress, size_of_file)
这有以下改进:
- 不使用
readlines()
,因此不将所有内容存储到内存中 - 每10000行仅打印一次
- 使用文件大小而不是行数来衡量进度,所以不必迭代文件两次