语句:with和tarfile

15 投票
3 回答
9491 浏览
提问于 2025-04-16 18:07

我尝试使用 with 语句和 tarfile 模块...

with tarfile.open('/dir/dir/dir.tar.gz', 'w:gz') as fl:
    fl.add('/dir/dir/dir/', arcname = '/')

所以它显示了以下内容:

Traceback (most recent call last):
File "", line 1, in
AttributeError: 'TarFile' object has no attribute '__exit__'

我试着创建一个 tar.gz 文件,并使用这个语句来关闭它,但出现了错误。问题出在哪里呢?

谢谢!

3 个回答

2

你的错误信息复制得不太对。应该是 AttributeError: 'TarFile' object has no attribute '__exit__'

你显然在使用一个早于2.7的Python版本,而2.7版本增加了对“上下文管理器”协议的支持(这对于使用 with 语句是必要的),并且这个支持是针对 tarfile 模块的。

你有两个选择:

(1) 升级到2.7 但是 要注意,文档中说明这个支持并不完全:"""一个TarFile对象可以在 with 语句中作为上下文管理器使用。当代码块执行完毕后,它会自动关闭。不过请注意,如果发生异常,打开的写入归档不会被最终化;只有内部使用的文件对象会被关闭。

(2) 继续使用2.6或者其他版本,手动用try/except/finally来处理。

7

也许你使用的Python标准库版本不够新。查看一下这份文档,里面提到:

  • 在2.7版本中新增:支持上下文管理器协议。

顺便说一下,当你在使用Python标准库时遇到不明白的行为,查阅文档应该是你首先要做的事情。特别是阅读那一页,如果你明白整个“上下文管理”系统(对象协议)是相对较新的,并且是通过Python中那个比较难找的with关键字来访问的,那么就能解答你的疑问。

这个对象协议实现了一些有用的隐式语义,比如关闭文件、释放锁以及其他清理和资源管理的事情……即使在出现异常的情况下也是如此。其实这就是在try:...finally:...的基础上加了一些语法糖,并且你可以为自己的类添加一些特性来利用这些支持。

要进一步理解这些内容,最好去阅读一下:with语句上下文管理器

16

你可以使用 contextlib.closing,比如:

from contextlib import closing
with closing(tarfile.open('/dir/dir/dir.tar.gz', 'w:gz')) as fl:
    fl.add('/dir/dir/dir/', arcname = '/')

来自文档的说明:

即使发生错误,当退出 with 块时,page.close() 也会被调用。

contextlib.closing 从 Python 2.5 开始就可以用了(可能甚至更早就有了...)。

撰写回答