【问题标题】:Python iterating forwards and backwards through a text file [duplicate]Python通过文本文件向前和向后迭代[重复]
【发布时间】:2014-11-18 11:05:09
【问题描述】:

您好,我有一个模糊的问题...

我想构建一个工具来搜索日志文件,并且我想要以下功能:

1) 搜索日志文件,直到找到给定的日志行。 2) 找到 1) 后向前跳转未知数量的行,直到满足条件。此时数据用于进行一些计算。 3) 完成 2) 后,我想返回到 1) 中找到的行并继续处理文件。

现在我可以很容易地执行 1) 和 2),只需遍历每一行:

for line in file

for 3) 我打算使用类似 file.seek(linenum) 的东西并继续遍历这些行。但是对于上述任何步骤,是否有更有效的方法?

谢谢

【问题讨论】:

  • 你能把文件加载到内存中吗?如果是,我认为更好的方法是使用正则表达式搜索一行(步骤 1)。
  • 很遗憾没有文件超过 10gb

标签: python iteration


【解决方案1】:

对于文件,使用tellseek 很容易解决:

o=open(myfile)
#read some lines
last_position= o.tell()
#read more lines
o.seek( last_position )
#read more lines again

请注意,与您在问题中提到的不同,seek 不采用行号。它需要一个字节偏移量。对于 ASCII 文件,字节偏移量也是字符偏移量,但这不适用于大多数现代编码。

没有“更有效”的方法可以做到这一点,AFAIK。从操作系统、内存、cpu 和磁盘的角度来看,这非常有效。从编程的角度来看有点笨拙,但不幸的是python没有提供克隆迭代器的标准方法

【讨论】:

    【解决方案2】:
    def read_until_condition(fd, condition, reset, apply=None):
        """
        Returns the position of the file in which the condition functuon is
        true
        :fd : a file descriptor
        :condition (function): a funtion that accepts a line
        :reset (bool): if True then the fd is returned to the initial position
        :apply (func): The function to apply to each line
    
        Returns:
        int the position of the file in which the condition is True
        """
        pos = None
        current_position = fd.tell()
    
        while True:
            pos = fd.tell()
            l = fd.readline()
    
           if l and apply is not None:
               apply(l)
    
           if not l or condition(l):
               break
    
        if reset:
            fd.seek(current_position)
    
        return pos
    
    
    if __name__ == '__main__':
    
        f = open('access_log', 'r')
        cf = lambda l: l.startswith('64.242.88.10 - - [07/Mar/2004:16:54:55 -0800]')
        pos = read_until_condition(f, cf, False)
        condition = lambda l: l.startswith('lj1090.inktomisearch.com - - [07/Mar/2004:17:18:41 -0800]')
    
        def apply(l):
            print l,
    
        read_until_condition(f, condition, True, apply)
    
        f.close()
    

    我不确切知道您需要什么,但类似上面的东西(根据您的需要进行修改)应该可以工作。

    我使用从这里下载的一些 apache 日志样本进行了测试。

    【讨论】:

      【解决方案3】:

      这个答案为大文件实现了一个高效的基于行的阅读器:https://stackoverflow.com/a/23646049/34088

      【讨论】:

        猜你喜欢
        • 2017-08-25
        • 1970-01-01
        • 1970-01-01
        • 2015-09-25
        • 2010-11-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多