假设我有一个BIG文件,其中包含一些我想忽略的行,以及一个file_function
带有文件对象的函数().我可以返回一个新的文件对象,其行满足某些条件而不首先读取整个文件,这种懒惰是重要的部分.
注意:我可以保存一个忽略这些行的临时文件,但这并不理想.
例如,假设我有一个csv文件(带有坏行):
1,2
ooops
3,4
Run Code Online (Sandbox Code Playgroud)
第一次尝试是创建新文件对象(使用与文件相同的方法)并覆盖readline
:
class FileWithoutCondition(file):
def __init__(self, f, condition):
self.f = f
self.condition = condition
def readline(self):
while True:
x = self.f.readline()
if self.condition(x):
return x
Run Code Online (Sandbox Code Playgroud)
如果file_name
仅使用readline
...则有效,但如果需要其他功能则不行.
with ('file_name', 'r') as f:
f1 = FileWithoutOoops(f, lambda x: x != 'ooops\n')
result = file_function(f1)
Run Code Online (Sandbox Code Playgroud)
使用StringIO的解决方案可能有效,但我似乎无法实现.
理想情况下,我们应该假设这file_function
是一个黑盒功能,特别是我不能只是调整它来接受一个生成器(但也许我可以调整一个生成器就像文件一样?).
有没有一种标准的方法来执行这种懒惰(skim-)读取通用文件?
注意:这个问题的激励性例子就是这个熊猫问题,其中只有一个readline
不足以开始pd.read_csv
工作......
将映射缩减方法与现有的 Python 工具结合使用。在此示例中,我使用正则表达式来匹配以 string 开头的行GET /index
,但您可以使用适合您的账单的任何条件:
import re
from collections import defaultdict
pattern = re.compile(r'GET /index\(.*\).html')
# define FILE appropriately.
# map
# the condition here serves to filter lines that can not match.
matches = (pattern.search(line) for line in file(FILE, "rb") if 'GET' in line)
mapp = (match.group(1) for match in matches if match)
# now reduce, lazy:
count = defaultdict(int)
for request in mapp:
count[request] += 1
Run Code Online (Sandbox Code Playgroud)
在我的笔记本电脑上,这会在几秒钟内扫描>6GB的文件。您可以进一步将文件分割成块并将它们提供给线程或进程。我不建议使用mmap
,除非您有足够的内存来映射整个文件(它不支持窗口)。
归档时间: |
|
查看次数: |
251 次 |
最近记录: |