python - 在阅读之前懒惰地过滤文件

标签 python file

假设我有一个大文件,其中包含一些我希望忽略的行,以及一个接受文件对象的函数 (file_function)。我能否返回一个新的文件对象,其行满足某些条件而不先读取整个文件,这个惰性是重要的部分。

注意:我可以只保存一个忽略这些行的临时文件,但这并不理想。

例如,假设我有一个 csv 文件(带有错误行):

1,2
ooops
3,4

第一次尝试是创建新的文件对象(使用与文件相同的方法)并覆盖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

这在 file_name 仅使用 readline 时有效...但如果它需要一些其他功能则无效。

with ('file_name', 'r') as f:
    f1 = FileWithoutOoops(f, lambda x: x != 'ooops\n')
    result = file_function(f1)

使用 StringIO 的解决方案可能有效,但我似乎做不到。

理想情况下,我们应该假设 file_function 是一个黑盒函数,具体来说,我不能仅仅调整它来接受一个生成器(但也许我可以将一个生成器调整为类文件?)。< br/> 是否有一种标准方法可以对通用文件进行这种惰性(略读)读取?

注意:这个问题的激励示例是 this pandas question ,只有 readline 不足以让 pd.read_csv 工作...

最佳答案

将 map-reduce 方法与现有的 Python 工具结合使用。在此示例中,我使用正则表达式来匹配以字符串 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

这会在我的笔记本电脑上几秒钟内扫描一个 >6GB 的文件。您可以进一步将文件分成 block 并将它们提供给线程或进程。使用 mmap 我不推荐,除非你有足够的内存来映射整个文件(它不支持窗口化)。

关于python - 在阅读之前懒惰地过滤文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15090685/

相关文章:

python - 使用 pandas DateTimeIndex 提取年份但出现错误

python - 如何更改 ttk.Combobox 中下拉菜单(即 tk.Listbox)事件背景的颜色

python - 使用随机函数(Python turtle 图形)

c++ - 在 vc++ 中仅从文件的完整路径中查找文件名

python - 在Python中逐行读取文件

python - 二叉树的所有元素列表

python - rdflib - 查询持久性存储

algorithm - 文件、月份、模块和伪代码

Linux 文件权限(深入)——数字到字符串表示法,反之亦然;附加文件权限

cocoa - 如果我尝试将项目替换为不同的卷,replaceItemAtURL 将不起作用