Python是否保留对列表中打开的文件的引用?

Python是否保留对列表中打开的文件的引用?,python,file,Python,File,我有一个程序,我需要保留一些在磁盘列表中打开文件的对象,并在程序完成后删除这些文件。然而,Python似乎保持了文件的打开状态,即使没有更多的对象引用应该打开它。我已经能够用下面的纯文件对象重新创建问题: import os filenames = ['a.txt', 'b.txt'] files = [open(f,'w') for f in filenames] for f_object in files: f_object.write("test") del files[:]

我有一个程序,我需要保留一些在磁盘列表中打开文件的对象,并在程序完成后删除这些文件。然而,Python似乎保持了文件的打开状态,即使没有更多的对象引用应该打开它。我已经能够用下面的纯文件对象重新创建问题:

import os

filenames = ['a.txt', 'b.txt']
files = [open(f,'w') for f in filenames]
for f_object in files:
    f_object.write("test")

del files[:]

for name in filenames:
    os.remove(name)
当我在Windows上运行此操作时,我得到了错误

Traceback (most recent call last):
  File ".\file_del.py", line 11, in <module>
    os.remove(name)
WindowsError: [Error 32] The process cannot access the file because it is being used by another process: 'b.txt'
更新2


我在下面将millimoose的答案标记为正确答案,因为它解决了我在这里介绍的文件抽象问题。不幸的是,它对我使用的GDAL对象不起作用。为了将来的参考,我深入挖掘并找到了未记录的
gdal.Dataset.\uuuu destroy\u swig\uuuz(ds)
函数,它似乎至少关闭了与数据集关联的文件。在删除与数据集关联的磁盘上的文件之前,我先调用它,这似乎有效。

您必须关闭这些文件

for f_object in files:
    f_object.write("test")
    f_object.close()

您需要使用该方法关闭文件。当垃圾回收器运行时,文件会自动关闭,但这种情况何时发生是不确定的

确保即使在遇到异常时也能确定地关闭文件的首选方法是使用
with
语句上下文管理器:

with open('filename') as f:
    # Do file operations on f
    ...

# At this scope, f is now closed, even if an exception was thrown

如果您使用的是Python2.5,则必须在程序开始时使用u语句从uuu未来uu导入编写
;如果您使用的是Python2.6或更高版本,那么这是不必要的。

循环变量
f\u对象的范围实际上是周围的函数/模块。这意味着即使清除列表,它也会保留对迭代中最后一个文件的引用。以下各项工作正常:

import os

filenames = ['a.txt', 'b.txt']
files = [open(f,'w') for f in filenames]
for f_object in files:
    f_object.write("test")

del files[:]
# Nuke the last reference.
del f_object 

for name in filenames:
    os.remove(name)
我想在你的原始代码中应该是
delband
。或者,将循环移动到函数中以避免循环变量泄漏:

import os

def write_to_files(files):
    for f_object in files:
        f_object.write("test")  

filenames = ['a.txt', 'b.txt']
files = [open(f,'w') for f in filenames]
write_to_files(files)

del files[:]

for name in filenames:
    os.remove(name)

Millimoose认为
f_object
仍保留对列表中最后一个文件的引用是正确的。您只需重置或删除该变量。我曾遇到过更奇怪的情况,在过去,人们莫名其妙地保留着参考资料。下面是一个方法,可以用来测试是否所有引用都已被垃圾收集。请注意,如果您试图从IPython内部使用此方法,则使用
weakref
s的方法会让您头痛不已

#!/bin/env python

import weakref
from sys import getrefcount

#Open two lists of files
f1 = [file('temp1.txt','w'), file('temp2.txt','w')]
f2 = [file('temp3.txt','w'), file('temp4.txt','w')]

#Loop over both to create arrays of weak references
weak_f1 = [weakref.ref(x) for x in f1]
weak_f2 = [weakref.ref(x) for x in f2]

#Note that x still contains a reference to f2[1]
print x

#Print the number of references for each file
print 'Note, temp4.txt has an extra reference.'
print 'temp1.txt ref count == %r' % getrefcount(weak_f1[0]())
print 'temp2.txt ref count == %r' % getrefcount(weak_f1[1]())
print 'temp3.txt ref count == %r' % getrefcount(weak_f2[0]())
print 'temp4.txt ref count == %r\n' % getrefcount(weak_f2[1]())

#Delete both arrays
print 'Deleting arrays.'
del f1[:]
del f2[:]

#Print the number of references again
print 'temp1.txt ref count == %r' % getrefcount(weak_f1[0]())
print 'temp2.txt ref count == %r' % getrefcount(weak_f1[1]())
print 'temp3.txt ref count == %r' % getrefcount(weak_f2[0]())
print 'temp4.txt ref count == %r\n' % getrefcount(weak_f2[1]())

#Note, temp4.txt still has two references while the others show MANY references
#This is because a reference to temp4.txt still exists in `x`.
#The the other files show many references because they are now pointed at `None`.
print 'All weak refs are now dead except the one still stored in `x`'
print weak_f1
print weak_f2, '\n'

#Delete `x` and this extra reference is gone
print 'Deleting `x`'
del x

#All references are now `None`
print 'Now we have lost our last file reference and all weakrefs are dead'
print weak_f1
print weak_f2

你有没有。。。关闭文件?我在这里抽象了问题,在原始问题中,我从GDAL库创建了一个GIS数据集。我没有访问GDAL对象引用的文件的权限。引用计数是相同的。@Brian文件应该在对象被GCed时关闭。@millimoose是的,这就是问题所在。为什么这里没有垃圾收集?@Rich哦,等等,其实很简单。在文件中的文件对象的
中,保留变量
文件对象中的最后一个文件。我不确定这对你的原始代码有何影响,但我猜类似的情况也会发生。在我的原始问题中,我没有访问该文件的权限来关闭它。但是一旦引用计数变为0,Python应该关闭这些文件。我不明白为什么在上面的问题中没有发生这种情况。看:这并不能真正解决OP观察到的微妙的奇怪之处<代码>文件。uuu del_uuu()
应关闭文件,但由于某些原因,最后打开的文件从未被删除。是的,永远不要依赖调用
del
。我们有
是有原因的。是的,我同意。
#!/bin/env python

import weakref
from sys import getrefcount

#Open two lists of files
f1 = [file('temp1.txt','w'), file('temp2.txt','w')]
f2 = [file('temp3.txt','w'), file('temp4.txt','w')]

#Loop over both to create arrays of weak references
weak_f1 = [weakref.ref(x) for x in f1]
weak_f2 = [weakref.ref(x) for x in f2]

#Note that x still contains a reference to f2[1]
print x

#Print the number of references for each file
print 'Note, temp4.txt has an extra reference.'
print 'temp1.txt ref count == %r' % getrefcount(weak_f1[0]())
print 'temp2.txt ref count == %r' % getrefcount(weak_f1[1]())
print 'temp3.txt ref count == %r' % getrefcount(weak_f2[0]())
print 'temp4.txt ref count == %r\n' % getrefcount(weak_f2[1]())

#Delete both arrays
print 'Deleting arrays.'
del f1[:]
del f2[:]

#Print the number of references again
print 'temp1.txt ref count == %r' % getrefcount(weak_f1[0]())
print 'temp2.txt ref count == %r' % getrefcount(weak_f1[1]())
print 'temp3.txt ref count == %r' % getrefcount(weak_f2[0]())
print 'temp4.txt ref count == %r\n' % getrefcount(weak_f2[1]())

#Note, temp4.txt still has two references while the others show MANY references
#This is because a reference to temp4.txt still exists in `x`.
#The the other files show many references because they are now pointed at `None`.
print 'All weak refs are now dead except the one still stored in `x`'
print weak_f1
print weak_f2, '\n'

#Delete `x` and this extra reference is gone
print 'Deleting `x`'
del x

#All references are now `None`
print 'Now we have lost our last file reference and all weakrefs are dead'
print weak_f1
print weak_f2