比方說,我只有8G的可用堆空間,並且我想將比這更大的文件轉換爲一系列較小的文件。如果我嘗試如何拆分大於內存大小的文件?
with open(fname) as f:
content = f.readlines()
我將耗盡內存,因爲它會嘗試加載整個文件。有沒有辦法打開文件,而無需在內存中加載整個文件,只需要從X到Y?
比方說,我只有8G的可用堆空間,並且我想將比這更大的文件轉換爲一系列較小的文件。如果我嘗試如何拆分大於內存大小的文件?
with open(fname) as f:
content = f.readlines()
我將耗盡內存,因爲它會嘗試加載整個文件。有沒有辦法打開文件,而無需在內存中加載整個文件,只需要從X到Y?
itertools.islice
是工作的好工具,但你需要考慮如何有效地使用它。例如,islice(f, 10, 20)
丟棄10行然後發出20行,因此這不是寫入的好方法。根據您編寫循環的方式,您可以刪除數據或重新掃描每次寫入的文件。
它也不是很明顯知道你什麼時候完成。 fileobj.writelines(isslice(f, 10))
會愉快地寫0行文件直到時間結束。你真的只知道你是在事實之後完成的,所以你可以測試你是否寫了一個零長度的文件來終止。
在這個例子中,我的大文件是100行長,我分成10行apeice ....這比8gig文件測試有點快。
import itertools
import os
lines_per_file = 10
with open('big.txt') as infp:
# file counter used to create unique output files
for file_count in itertools.count(1):
out_filename = 'out-{}.txt'.format(file_count)
with open(out_filename, 'w') as outfp:
# write configured number of lines to file
outfp.writelines(itertools.islice(infp, lines_per_file))
# break when no extra data written
if os.stat(out_filename).st_size == 0:
os.remove(out_filename)
break
RE:「知道你何時完成並不明顯」 - 正是我爲什麼要對其他答案發表評論「我怎麼知道我何時到達EOF?」 – amphibient
文件句柄可以用作文件中行的迭代器。你想要的是來自該迭代器的特定切片。在標準庫中有一個方便的itertools.islice()
函數可以完成這個功能。
from itertools import islice
line_slice = (10, 20)
with open(fname) as f:
content = islice(f, *line_slice)
上面的內容或多或少相當於f.readlines()[10:20]
。
請注意,islice()
的輸出是另一個迭代器。幸運的是writelines()
接受迭代器,所以不需要將其轉換爲臨時列表。這也意味着,如果您直接將其傳遞給writelines()
,則在任何時候都不會在內存中保留多行內容。
with open(out_fname, 'w') as f:
f.writelines(content)
你能寫一個簡短的方法和參數的描述嗎? –
該方法看起來不錯,但是,如何知道何時到達EOF?它不會拋出異常 – amphibient
迭代f而不是用readlines()讀取整個文件 – jordanm
這種情況下每個迭代單元是什麼? – amphibient
這可能是一個重複:http://stackoverflow.com/questions/2363483/python-slicing-a-very-large-binary-file –