我正在尝试读取一个gzip文件(大小约为150 MB)并使用此脚本(我知道写得不好):
import gzip
f_name = 'file.gz'
a = []
with gzip.open(f_name, 'r') as infile:
for line in infile:
a.append(line.split(' '))
new_array1 = []
for l in a:
for i in l:
if i.startswith('/bin/movie/tribune'):
new_array1.append(l)
filtered = []
for q in range(0, len(new_array1)):
filtered.append(new_array1[q])
#at this point filtered array can be printed
问题是我能够使用这种技术将高达50 MB的文件读入数组,但80 MB及以上的文件大小无法读取。我正在使用的技术是否存在某些问题或是否存在内存约束?如果这是第二种情况,那么在python数组中读取大型gz文件(大于100 MB)的最佳技术是什么?任何帮助将不胜感激。
注意:我没有使用NumPy,因为我遇到了一些严重的问题,我的服务器上的C编译器是numpy所必需的,因此我无法拥有它。所以,请建议使用原生Pythonic方法(或NumPy以外的任何其他方法)。感谢。
答案 0 :(得分:5)
我的猜测是问题是在你的代码中构建a
,因为如果你的.gz那么大,这无疑会包含大量的条目。这种修改应该可以解决这个问题:
import gzip
f_name = 'file.gz'
filtered = []
with gzip.open(f_name, 'r') as infile:
for line in infile:
for i in line.split(' '):
if i.startswith('/bin/movie/tribune'):
filtered.append(line)
break # to avoid duplicates
答案 1 :(得分:1)
如果您的问题是内存消耗(您没有包含错误消息...),则可以通过使用generators避免存储临时列表来节省大量内存。
E.g。
import gzip
f_name = 'file.gz'
def get_lines(infile):
for line in infile:
yield line.split()
def filter1(line_tokens):
return any( token.startswith('/bin/movie/tribune') for token in line_tokens )
def filter2(line_tokens):
# was there a filter2?
return True
infile = gzip.open(f_name, 'r')
filtered = ( line_tokens for line_tokens in get_lines(infile) if filter1(line_tokens) and filter2(line_tokens) )
for line in filtered:
print line
在我的示例中filter2
是微不足道的,因为您的filtered
列表似乎只是new_array1
的一个(未经过滤的)副本...
这样,您就可以避免将整个内容存储在内存中。请注意,由于filtered
是一个生成器,因此您只能迭代一次。如果您确实需要完整存储,请执行filtered = list(filtered)