在Python中嵌套'WITH'语句

31 投票
6 回答
23350 浏览
提问于 2025-04-15 17:32

原来“with”这个词在网上搜索起来挺有意思的。

有没有人知道在Python中嵌套“with”语句是怎么回事?
我在写一个脚本的时候,遇到了一个很难抓住的bug,我怀疑这可能是因为我在这样做:

with open(file1) as fsock1:
    with open(file2, 'a') as fsock2:
        fstring1 = fsock1.read()
        fstring2 = fsock2.read()

当我尝试从fsock2中read()时,Python会报错。经过调试器检查后发现,它认为这个文件是空的。其实这并不太让人担心,除非我在调试器中运行完全相同的代码,但不使用with语句时,发现文件里其实有很多文字...

我现在打算假设嵌套使用with语句是不好的做法,但如果有更懂的人有不同的看法,我很想听听。

6 个回答

9

在调试器中检查后发现,这是因为它认为文件是空的。

我觉得这是因为它实际上无法读取任何内容。即使它能读取,当你往文件里添加内容时,指针会移动到文件的末尾,为写入做好准备。

这些 with 语句对我来说都很好用:

with open(file1) as f:
    with open(file2, 'r') as g:   # Read, not append.
        fstring1 = f.read()
        fstring2 = g.read()

需要注意的是,使用 contextlib.nested,正如其他人所建议的,可能会带来一些麻烦。假设你这样做:

with contextlib.nested(open(file1, "wt"), open(file2)) as (f_out, f_in):
   ...

这里的上下文管理器是一个一个创建的。这意味着如果打开 file2 失败(比如说,它不存在),那么你就无法正确结束 file1,只能依赖垃圾回收器来处理。这可能会导致很糟糕的结果。

12

据我所知,使用追加模式 'a' 打开的文件是无法读取的。

60

我在Python的文档中找到了这个解决方案。你可以看看这个(Python 3)或者这个(Python 2)

如果你在使用Python 2.7及以上版本,可以这样使用:

with open(file1) as fsock1, open(file2, 'a') as fsock2:
    fstring1 = fsock1.read()
    fstring2 = fsock2.read()

这样可以避免不必要的缩进。

撰写回答