【问题标题】:Parsing large, possibly compressed, files in Python在 Python 中解析大的、可能是压缩的文件
【发布时间】:2017-08-21 13:37:22
【问题描述】:

我正在尝试逐行解析一个大文件以获取相关信息。 我可能会收到未压缩或 gzip 压缩的文件(我可能需要在稍后阶段编辑 zip 文件)。

我正在使用下面的代码,但我觉得,因为我不在with语句中,我没有逐行解析文件,实际上是在将整个文件file_content加载到内存中。

if ".gz" in FILE_LIST['INPUT_FILE']:
    with gzip.open(FILE_LIST['INPUT_FILE']) as input_file:
        file_content = input_file.readlines()
else:
    with open(FILE_LIST['INPUT_FILE']) as input_file:
        file_content = input_file.readlines()

for line in file_content:
    # do stuff

对于我应该如何处理这个问题有什么建议吗? 我不希望在代码块之外解压缩文件,因为这需要是通用的,而且我必须整理多个文件。

【问题讨论】:

  • 使用readline()而不是readlines()逐行读取文件
  • 我认为当我到达for line in file_content: 时,我已经打开、读入内存并关闭了文件。我可以按原样使用readline(),但我必须复制两个if else: 分支的代码。

标签: python python-2.7 gzip


【解决方案1】:

readlines 完全读取文件。所以大文件是不行的。

像你正在做的那样做 2 个上下文块,然后在它们之外使用 input_file 句柄不起作用(对关闭的文件进行操作)。

为了两全其美,我会为上下文块使用三元条件(确定是否必须使用opengzip.open),然后在行上进行迭代。

open_function = gzip.open if ".gz" in FILE_LIST['INPUT_FILE'] else open
with open_function(FILE_LIST['INPUT_FILE'],"r") as input_file:
    for line in input_file:

请注意,我添加了“r”模式以确保处理文本而不是二进制(gzip.open 默认为二进制)

替代方案:open_function 可以设为通用,因此它不依赖于 FILE_LIST['INPUT_FILE']

open_function = lambda f: gzip.open(f,"r") if ".gz" in f else open(f)

一旦定义,就可以随意重用

with open_function(FILE_LIST['INPUT_FILE']) as input_file:
    for line in input_file:

【讨论】:

  • 我会把那长长的不可读的with 声明分开。首先确定您将如何打开文件,fopen = gzip.open if ".gz" in FILE_LIST['INPUT_FILE'] else open,然后做剩下的,with fopen(FILE_LIST['INPUT_FILE']) as input_file: ...
  • 不能取悦所有人 :) lambda 版本更好,因为它可以重复使用(我不喜欢复制/粘贴 FILE_LIST['INPUT_FILE']
  • @Jean-FrançoisFabre 我已经实现了你的代码,它就像一个魅力,感谢你的帮助和非常详细的解释!
猜你喜欢
  • 2010-12-23
  • 1970-01-01
  • 1970-01-01
  • 2011-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-25
相关资源
最近更新 更多