Python “for line in file object”读取文件的方法

Python “for line in file object”读取文件的方法,python,line,Python,Line,我正试图找出读取/处理超大文件行的最佳方法。 我只是试试看 for line in f: 我的部分脚本如下所示: o=gzip.open(file2,'w') LIST=[] f=gzip.open(file1,'r'): for i,line in enumerate(f): if i%4!=3: LIST.append(line) else: LIST.append(line) b1=[ord(x) for x in line]

我正试图找出读取/处理超大文件行的最佳方法。 我只是试试看

for line in f:
我的部分脚本如下所示:

o=gzip.open(file2,'w')
LIST=[]
f=gzip.open(file1,'r'):
for i,line in enumerate(f):
   if i%4!=3:
      LIST.append(line)

   else:
      LIST.append(line)
      b1=[ord(x) for x in line]
      ave1=(sum(b1)-10)/float(len(line)-1)
      if (ave1 < 84):
         del LIST[-4:]
output1=o.writelines(LIST)
我的file1大约是10GB;当我运行脚本时,内存使用量一直增加到15GB,没有任何输出。这意味着计算机仍在尝试先将整个文件读入内存,对吗?这与使用readline没有什么区别

然而,在岗位上: 斯里卡告诉我: f中的for行将文件对象f视为一个iterable,它自动使用缓冲IO和内存管理,因此您不必担心大文件

但显然我还是需要担心大文件..我真的很困惑。 thx

编辑: 在我的数据中,每4行是一组。
目的是在每4行上进行一些计算;根据计算结果,决定是否需要追加这4行。因此,写行是我的目的。

即使在使用枚举器之后,内存仍保持inc.的原因是因为您正在使用LIST.appendline。这基本上是将文件的所有行累积到一个列表中。显然,这一切都在记忆中。您需要找到一种方法来避免像这样累积行。阅读、处理并继续下一步

另外一种方法是将文件分块读取,事实上,一次读取一行符合此标准,1chunk==1line,即读取文件过程的一小部分,然后读取下一块等。我仍然认为这是读取python大小文件的最佳方法

with open(...) as f:
    for line in f:
        <do something with line>

with语句处理打开和关闭文件,包括在内部块中引发异常时。f中的for行将文件对象f视为一个iterable,它自动使用缓冲IO和内存管理,因此您不必担心大文件。

即使在使用枚举器之后,内存仍保持不变的原因是因为您使用的是LIST.appendline。这基本上是将文件的所有行累积到一个列表中。显然,这一切都在记忆中。您需要找到一种方法来避免像这样累积行。阅读、处理并继续下一步

另外一种方法是将文件分块读取,事实上,一次读取一行符合此标准,1chunk==1line,即读取文件过程的一小部分,然后读取下一块等。我仍然认为这是读取python大小文件的最佳方法

with open(...) as f:
    for line in f:
        <do something with line>

with语句处理打开和关闭文件,包括在内部块中引发异常时。f中的for行将文件对象f视为一个iterable,它自动使用缓冲IO和内存管理,因此您不必担心大文件。

由于您将所有行添加到列表中,并且有时仅从列表中删除一些行,因此列表变得越来越长。存储在列表中的所有行都将占用内存。如果不想占用内存,不要将所有行都放在列表中


此外,您的脚本似乎在任何地方都不会产生任何输出,因此其要点并不十分清楚。

由于您将所有行添加到列表中,并且只是偶尔从列表中删除一些行,因此列表变得越来越长。存储在列表中的所有行都将占用内存。如果不想占用内存,不要将所有行都放在列表中


此外,您的脚本似乎在任何地方都不会产生任何输出,因此其要点并不十分清楚。

好的,您已经从其他注释/答案中了解到您的问题所在,但让我简单地说明一下

您一次只在内存中读取一行,但通过添加到列表,您将其中的很大一部分存储在内存中

为了避免这种情况,如果您的算法足够复杂,您需要在文件系统或磁盘上的数据库中存储一些内容,以便以后查找

从我看来,您似乎可以轻松地增量编写输出。例如,您当前正在使用一个列表来存储要写入输出的有效行以及可能在某个点删除的临时行。为了提高内存使用效率,您希望在知道临时列表中的行是有效输出后立即写入这些行


总之,使用您的列表只存储您根据进行计算所需的临时数据,一旦您准备好了一些有效数据以供输出,您只需将其写入磁盘并用python从主内存中删除即可,这意味着您不应再对其进行任何引用。

好,从其他评论/答案中你已经知道你的问题所在,但让我简单地陈述一下

您一次只在内存中读取一行,但通过添加到列表,您将其中的很大一部分存储在内存中

为了避免这种情况,如果您的算法足够复杂,您需要在文件系统或磁盘上的数据库中存储一些内容,以便以后查找

据我所知 似乎您可以轻松地增量编写输出。例如,您当前正在使用一个列表来存储要写入输出的有效行以及可能在某个点删除的临时行。为了提高内存使用效率,您希望在知道临时列表中的行是有效输出后立即写入这些行


总之,使用您的列表只存储您根据进行计算所需的临时数据,并且一旦您准备好了一些有效数据以供输出,您只需将其写入磁盘并用python将其从主内存中删除,这将意味着您不应再对其进行任何引用。

此函数结束时,您将读取的所有行都存入内存,然后立即将它们写入文件。也许您可以尝试以下过程:

在前3行中读入所需的行。 在第4行,附加该行并执行计算。 如果要查找的是计算结果,请将集合中的值刷新到文件中。 不管接下来发生什么,创建一个新的集合实例。 我还没有试过,但它可能看起来像这样:

o=gzip.open(file2,'w')
f=gzip.open(file1,'r'):
LIST=[]

for i,line in enumerate(f):
   if i % 4 != 3:
      LIST.append(line)
   else:
      LIST.append(line)
      b1 = [ord(x) for x in line]
      ave1 = (sum(b1) - 10) / float(len(line) - 1

      # If we've found what we want, save them to the file
      if (ave1 >= 84):
         o.writelines(LIST)

      # Release the values in the list by starting a clean list to work with
      LIST = []

编辑:考虑到你的文件太大了,这可能不是最好的技术,因为你需要将所有的行写入文件,但不管怎样,这可能值得研究。

看起来在这个函数结束时,你将读取的所有行都放入内存,然后立即将它们写入文件。也许您可以尝试以下过程:

在前3行中读入所需的行。 在第4行,附加该行并执行计算。 如果要查找的是计算结果,请将集合中的值刷新到文件中。 不管接下来发生什么,创建一个新的集合实例。 我还没有试过,但它可能看起来像这样:

o=gzip.open(file2,'w')
f=gzip.open(file1,'r'):
LIST=[]

for i,line in enumerate(f):
   if i % 4 != 3:
      LIST.append(line)
   else:
      LIST.append(line)
      b1 = [ord(x) for x in line]
      ave1 = (sum(b1) - 10) / float(len(line) - 1

      # If we've found what we want, save them to the file
      if (ave1 >= 84):
         o.writelines(LIST)

      # Release the values in the list by starting a clean list to work with
      LIST = []
编辑:考虑到您的文件太大,这可能不是最好的技术,因为您必须将所有行写入文件,但无论如何,这可能值得研究。

如果不使用with语句,则必须关闭文件的处理程序:

o.close()

f.close()
如果不使用with语句,则必须关闭文件的处理程序:

o.close()

f.close()


只要ave1>=84,您刚才添加到列表中的4个元素就会成为永久元素,不是吗?那么,这种情况经常发生吗?是的。当ave1>=84时,它不会被删除。大多数时候我都会发生是的,现在我明白我的问题了。你是如何确定内存使用率的?还有,你到底想做什么?84号有什么特别之处?你要寻找的数学属性是什么?可能是ave1>=84的任何时候的重复,你刚刚添加到列表中的这4个元素将成为永久元素,不是吗?那么,这种情况经常发生吗?是的。当ave1>=84时,它不会被删除。大多数时候我都会发生是的,现在我明白我的问题了。你是如何确定内存使用率的?还有,你到底想做什么?84号有什么特别之处?你要找的数学性质是什么?好的,srikar,thx!我明白我的问题在哪里!但是,我该怎么做才能不累加这些行呢?因此,不要将每一行都添加到列表中,而是尝试处理该行并存储该处理的结果。因为我看到您正在对某些行进行一些计算,所以只存储该计算&而不是整个行。但我的目的是附加这些行……我根据每四行的计算来决定是否附加行。您需要解释更多。但我仍然觉得这是可以解决的,不需要积累所有的行。就像我的脚本所示:对于第一行、第二行、第三行,我只是简单地附加它们;然后到了第四行,我首先需要做一些计算,只有当它通过阈值时,我不仅会保留第四行,还会保留前三行。但显然,当前的脚本无法做到这一点。我还是把你弄糊涂了吗好的,谢谢!我明白我的问题在哪里!但是,我该怎么做才能不累加这些行呢?因此,不要将每一行都添加到列表中,而是尝试处理该行并存储该处理的结果。因为我看到您正在对某些行进行一些计算,所以只存储该计算&而不是整个行。但我的目的是附加这些行……我根据每四行的计算来决定是否附加行。您需要解释更多。但我仍然觉得这是可以解决的,不需要积累所有的行。就像我的脚本所示:对于第一行、第二行、第三行,我只是简单地附加它们;然后到了第四行,我首先需要做一些计算,只有当它通过阈值时,我不仅会保留第四行,还会保留前三行。但显然,当前的脚本无法做到这一点。我还是把你弄糊涂了吗thx…是的,这只是我脚本的一部分。我会展示所有的thx…是的,这只是我脚本的一部分。我会
感谢你们的友好解释;现在我完全明白我的问题了。看看道格·斯温的评论,这正是我需要的。谢谢你们!好消息:,看起来道格对你想做的事情有很好的把握;现在我完全明白我的问题了。看看道格·斯温的评论,这正是我需要的。谢谢你们!好消息:,看起来道格对你想做的事情有很好的把握。