Python: 不需要csv.close()?

61 投票
3 回答
135076 浏览
提问于 2025-04-16 01:04

我正在使用CSV模块来读取一个用制表符分隔的文件。下面是我的代码:

z = csv.reader(open('/home/rv/ncbi-blast-2.2.23+/db/output.blast'), delimiter='\t')

但是当我在脚本的最后加上Z.close()时,出现了一个错误,提示“csv.reader对象没有'close'这个属性”。

z.close()

那么我该怎么关闭“Z”呢?

3 个回答

8

你并不是关闭 reader() 方法的结果,而是关闭 open() 方法的结果。所以,你需要用两条语句:foo=open(...); bar=csv.reader(foo)。然后你可以调用 foo.close() 来关闭文件。

把本来可以用两条语句写得更清晰、更好理解的东西硬要写成一条,是不会得到额外的分数的。

40

你不需要直接关闭CSV读取器;相反,你应该关闭正在使用的文件对象。比如,在你的例子中,你可以这样做:

f = open('/home/rv/ncbi-blast-2.2.23+/db/output.blast')
z = csv.reader(f, delimiter='\t')
...
f.close()

如果你使用的是较新的Python版本,可以使用with语句,比如:

with open('/home/rv/ncbi-blast-2.2.23+/db/output.blast') as f:
    z = csv.reader(f, delimiter='\t')
    ...

这样做的好处是,即使你在with块中抛出异常或者提前返回,f也会被关闭。而在之前的例子中,如果出现这种情况,文件可能会一直保持打开状态。换句话说,这基本上等同于一个try/finally块,比如:

f = open('/home/rv/ncbi-blast-2.2.23+/db/output.blast')
try:
    z = csv.reader(f, delimiter='\t')
    ...
finally:
    f.close()
66

这个“读取器”其实就是一个解析器。当你请求一行数据时,它会把读取的工作交给底层的 file 对象,然后把结果转换成一组字段。这个读取器本身并不管理任何需要在使用完后清理的资源,所以你不需要去关闭它;这样做没有意义。

不过,你要确保关闭底层的 file 对象,因为它确实管理着一个资源(一个打开的文件描述符),这个资源是需要清理的。下面是关闭的方法:

with open('/home/rv/ncbi-blast-2.2.23+/db/output.blast') as f:
    z = csv.reader(f, delimiter='\t')
    # do whatever you need to with z

如果你不太了解 with 语句,可以把它理解为把内容放在一个 try...finally 块里,最后会在 finally 部分关闭文件。

希望这不成问题(如果成问题,那你真的需要更新到更新版的 Python),不过 with 语句是在 Python 2.5 中引入的,在那个版本中你需要用 __future__ 导入来启用它。如果你使用的是更老的 Python 版本,那你就得自己用 try...finally 来关闭文件。


感谢 Jared 指出关于 with 语句的兼容性问题。

撰写回答