【问题标题】:The most efficient (or professional) way to read, proccess and write a file with Python?使用 Python 读取、处理和写入文件的最有效(或专业)方法?
【发布时间】:2018-07-10 01:09:50
【问题描述】:

我需要编写一个 python 脚本来读取一个大的日志文件(1GB+),在每一行中提取 IP 地址,存储这些 IP,删除重复项,在另一个文件中找到与这些 IP 相关的主机名并将主机名重写为包含原始数据的新日志文件。

现在的问题是:处理内存、文件等的最佳方式是什么?我的意思是,我看到了两种方法:

  1. 读取原始日志文件,提取IP并写入新文件(tmp_IPS.txt,删除欺骗,在另一个文件(hostnames.txt)上逐行搜索这些IP,将结果写入tmp_IPS.txt,读取和重写原始日志文件。在这种情况下,我将处理更少的 IP(没有欺骗)。
  2. 读取原始日志文件,读取 IP 并在 hostnames.txt 上搜索每个 IP,在原始日志文件 + 主机名上写入行。在这种情况下,我会处理很多重复的 IP。我也可以将找到的 IP 和主机名写入新文件或内存中,但我真的不知道哪个更好。

【问题讨论】:

    标签: python memory file-io


    【解决方案1】:

    我预见到这个典型的常见任务有 2 种可能的场景,所以我将非常简要地评论它们。

    场景 1) 重用日志文件输入数据进行多个查询或从中创建一个或多个输出文件。

    1. 首先衡量使用 Python 内置块从整个文件中创建高效的内存数据结构需要多长时间,如果从整个日志文件中读取和创建一个简单的字典需要几秒钟的时间可能不值得浪费更多时间编写更复杂的解决方案。

    2. 上一步是不是非常昂贵的操作?如果是这种情况,并且您要经常重复使用输入数据,我可能会从中创建一个数据库(NoSQL 或关系,具体取决于处理类型)。如果您要经常使用日志文件数据,这种方式可能是值得的。

    Scenario2)您只想处理一次输入数据并放弃脚本。

    如果是这种情况,最简单的解决方案是从巨大的日志文件中提取非常少的数据子集,这样您就可以尽可能快地进行迭代。获得这些数据后,创建实现整个过程的整个脚本,一旦您确定脚本已经过测试并准备就绪,只需让它运行几秒钟(我可以将手指放在运行一个简单的像这样的脚本应该花费不到 1 分钟的时间)。

    也就是说,您已经到了需要像这样处理和解析巨大的日志文件的地步,这表明您可能应该开始考虑以更有效的方式存储日志数据...例如,使用诸如kibana 或类似名称。

    【讨论】:

    • BPL,谢谢!我的意图是将此脚本用作某些事件响应案例的基础,并且日志文件会因案例而异。我的第一个想法是分块读取日志文件,处理这些块并继续。我至少会考虑使用数据库作为主机名。我会在一些测试后报告
    【解决方案2】:

    在这种情况下处理大日志文件最有效的方法是逐行同时读取和写入,以避免将大文件加载到内存中。如果hostnames.txt 相对较小,您应该首先将IP 到主机名的映射文件hostnames.txt 加载到字典中;否则您应该考虑将映射存储在索引数据库中)

    【讨论】:

    • 谢谢你。主机名文件不超过 30MB,我真的不知道在内存中维护一个大小的字典是否是一个好习惯。关于使用数据库,这在 Python 中对我来说是一个新事物,但我会考虑。
    • 不客气。 30MB 对于字典来说足够小了。然后使用 dict。
    【解决方案3】:

    您打算如何从temp_IPS.txt 中删除重复项?简单地避免在文件中插入重复的 IP 地址(并​​避免在内存中存储重复的 IP 地址)也许更有意义。

    就 Python 文件 I/O 的速度而言,它可能取决于您使用的 Python 版本。假设您选择了 Python 3,则循环如下:

    for line in file.readlines() :
        # Code to deal with the string on each line
    

    假设您的文件格式正确,可能会非常适合您的用例。

    我建议以下策略:

    1. 打开原始文件进行阅读
    2. 打开一个新文件以存储所需的输出以供写入
    3. 遍历原始文件并仅在找到非重复 IP 时写入新文件(这需要将所有以前找到的 IP 存储在内存中)

    有很多方法可以将 IP 地址存储在内存中,有些更节省空间,有些更节省时间。这取决于您使用的硬件以及一次需要读取多少数据。

    【讨论】:

      【解决方案4】:
      1. 您应该阅读 hostnames.txt 并将 IP 映射到主机名 使用dict

      2. 然后您应该读取batches 中的文件并使用dict.get() 检查主机名,即host = host_dict.get(ip, None)

      3. 我不知道你说的是什么意思

        将主机名重写为包含原始数据的新日志文件

      但是你可以open()一个文件非常简单地追加

      with open('new_logfile', 'a') as logfile:
          logfile.write(data_to_append)
      

      【讨论】:

      • 对于 1 和 2,我要检查一下。对于 3,我不想修改原始文件,但我需要将这些信息与主机名放在同一个文件中。谢谢!
      猜你喜欢
      • 2010-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多