回答此问题可获得 20 贡献值,回答如果被采纳可获得 50 分。
<p><strong>在循环中打开一系列大型.gz文件时,考虑到这些文件在单独打开时不会产生错误,如何避免MemoryError?</strong></p>
<p>我在我的计算机中存储了一系列.gz文件(每个文件大达440MB)(如果您想用它们来尝试代码,它们就是<a href="http://irsa.ipac.caltech.edu/2MASS/download/allsky/" rel="nofollow noreferrer">this directory</a>中的psc文件)。我想打开第一个并用它做一些操作,然后打开第二个并做一些操作等等。在</p>
<p>当我执行这段代码时</p>
<pre><code>import gzip
files=['thing1.gz', 'thing2.gz']
x=list(gzip.open(files[0],"r"))
</code></pre>
<p>,或此代码</p>
^{pr2}$
<p>,也就是说,当我分开打开每个文件时,即使它们的大小很大,我也不会遇到任何问题。在</p>
<p>但我是一个懒惰的人,所以我想对许多文件都这样做,而不必手动执行另一个文件的脚本。所以我需要一个for循环</p>
<pre><code>import gzip
files=['thing1.gz', 'thing2.gz']
for current_file in files:
x=list(gzip.open(current_file,"r"))
</code></pre>
<p>现在是我遇到问题的时候,更确切地说是记忆错误。我只是假设x变量将被重命名,并且前一个文件的任何剩余部分都将被覆盖。在</p>
<p>我搜索过许多类似的问题(我认为这不是重复的,因为所有这些相似的问题都是用一种或另一种方法解决的,但我的问题却无法解决)。在</p>
<p>为了节省您的时间,以下是我尝试过但未能解决问题的解决方案:</p>
<p><strong>失败的解决方案#1</strong></p>
<pre><code>import gzip
files=['thing1.gz', 'thing2.gz']
for current_file in files:
x=list(gzip.open(current_file,"r"))
del x
</code></pre>
<p>这不起作用,也不象在另一个线程中建议的那样等待一段时间。在</p>
<pre><code>import gzip
import time
files=['thing1.gz', 'thing2.gz']
for current_file in files:
x=list(gzip.open(current_file,"r"))
time.sleep(120)
del x
</code></pre>
<p>创建一个删除所有不重要的变量的函数也不建议在另一个线程中使用(据我所知,它和del是一样的,所以为什么它应该起作用呢?)。在</p>
<pre><code>import gzip
def clearall():
not_variables=[var for var in globals() if (var[:2],var[-2:])==("__","__")]
white_list=["files","gzip","clearall"]
black_list=[var for var in globals() if var not in white_list+not_variables]
for var in black_list:
del globals()[var]
files=['thing1.gz', 'thing2.gz']
for current_file in files:
x=list(gzip.open(current_file,"r"))
clearall()
</code></pre>
<p><strong>失败的解决方案#2</strong></p>
<p>关闭文件是另一个不起作用的想法</p>
<pre><code>import gzip
files=['thing1.gz', 'thing2.gz']
for current_file in files:
x=gzip.open(current_file,"r")
y=list(x)
x.close()
del y
</code></pre>
<p><strong>失败的解决方案#3</strong></p>
<p>像很多类似问题中所说的那样,强制垃圾回收器也会因为某些原因(也许我还没有理解它是如何工作的)。在</p>
<pre><code>import gzip
import gc
files=['thing1.gz', 'thing2.gz']
for current_file in files:
x=list(gzip.open(current_file,"r"))
gc.collect()
</code></pre>
<p>因为<a href="https://stackoverflow.com/a/48843084/7306986">Jean-François Fabre pointed</a>这是垃圾收集器的一个坏用法(我不编辑前面的代码,因为我在一些线程中看到它是以这种方式编写的,所以我不编辑前面的代码,因为可能有助于某些人理解它)。在</p>
<p>遗憾的是,新的代码仍然不起作用</p>
<pre><code>import gzip
import gc
files=['thing1.gz', 'thing2.gz']
for current_file in files:
x=list(gzip.open(current_file,"r"))
x=None
gc.collect()
</code></pre>
<p><strong>失败的解决方案#4</strong></p>
<p>然后,我认为我是一个聪明的女孩,我试着做了两个scrpt;第一个打开一个特定的文件(谁的名字是在一个txt文档中指定的,这个文件显然也必须被打开)并对该文件进行一些操作,而另一个只是用当前文件名创建的txt文件,它必须由另一个打开为该文件编写脚本并运行它(在循环中)。也就是说,我将脚本分成两个;一个打开de文件,另一个创建循环,以便打开所有文件。这在我看来是合乎逻辑的,因为当我分开打开每个文件时没有问题。我只需要按顺序和自动地用另一个脚本打开它们!但事实证明这也行不通。在</p>
<p>脚本的另一个循环是:</p>
<pre><code>import os
files=['thing1.gz', 'thing2.gz']
for current_file in files:
temporary_file=open("temp.txt","w")
temporary_file.write(current_file)
temporary_file.close()
execfile("file_open_and_process.py")
os.remove("temp.txt")
</code></pre>
<p>这是打开的文件_进程.py由第一个脚本使用:</p>
<pre><code>import gzip
current_file=open("temp.txt","r").read()
x=list(gzip.open(current_file,"r"))
</code></pre>
<p><strong>失败的解决方案#5</strong></p>
<p>另一个想法是将所有打开和工作的文件作为一个函数,然后在循环中调用它,以便变量作为局部变量而不是全局变量存储在内存中,就像前面说的<a href="https://stackoverflow.com/questions/29904161/beautifulsoup-memoryerror-when-opening-several-files-in-directory">in yet another thread</a>。但这也不管用。在</p>
<pre><code>import gzip
def open_and_process(file):
return list(gzip.open(current_file,"r"))
files=['thing1.gz', 'thing2.gz']
for current_file in files:
x=open_and_process(current_file)
del x
</code></pre>
<p>对于我来说,理解为什么会发生这种情况非常重要,或者至少找到一个解决方案,让我在代码中更改很少(与这些玩具示例相比,代码非常复杂)。在</p>
<p>提前谢谢你!在</p>