在 Python 中嵌套“WITH”语句

Posted

技术标签:

【中文标题】在 Python 中嵌套“WITH”语句【英文标题】:Nesting 'WITH' statements in Python 【发布时间】:2010-12-31 17:08:30 【问题描述】:

事实证明,“with”是一个在互联网上搜索的有趣词。

有谁知道在 python 中嵌套语句是怎么回事? 我一直在跟踪我一直在编写的脚本中的一个非常狡猾的错误,我怀疑这是因为我正在这样做:

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

当我从 fsock2 尝试 read() 时,Python 会抛出异常。在调试器中检查时,这是因为它认为文件是空的。这不会令人担忧,除非在调试解释器中运行完全相同的代码而不是在 with 语句中向我显示该文件实际上充满了文本......

我将继续假设,目前嵌套 with 语句是不可以的,但如果知道更多的人有不同的意见,我很乐意听到。

【问题讨论】:

【参考方案1】:

我在 python 的文档中找到了解决方案。你可能想看看this (Python 3) 或this (Python 2)

如果你运行的是 python 2.7+,你可以像这样使用它:

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

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

【讨论】:

【参考方案2】:

AFAIK 您无法读取以附加模式打开的文件 'a'

【讨论】:

当我意识到同样的事情时,我正要评论我自己的问题。我觉得……现在很傻。【参考方案3】:

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

我认为这是因为它实际上无法读取任何内容。即使可以,当您追加到文件时,查找指针也会移动到文件的末尾以准备写入。

这些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 并且您必须将其留给垃圾收集器。这可能是一件非常糟糕的事情。

【讨论】:

"...那么您将无法正确完成..." 这是不正确的。基于Python docs,第二个with 语句将在第一个语句开始之前不会执行。复合 with 语句在语义上等同于嵌套的 with 语句。【参考方案4】:

嵌套with 语句没有问题——相反,您打开file2 进行追加,因此您无法从中读取。

如果您不喜欢嵌套with 语句,无论出于何种原因,您通常可以使用contextlib.nested 函数来避免这种情况。但是,它不会使损坏的代码(例如,打开文件以进行追加然后尝试读取它的代码)工作,也不会在词法上嵌套 with 语句破坏本来很好的代码。

【讨论】:

【参考方案5】:

至于搜索“with”,在词前加上“+”可以防止google忽略。

【讨论】:

这曾经是真的。现在你必须用引号括起来,即"with" 这不是手头问题的答案(是的,我知道这个问题已有 10 年历史了)

以上是关于在 Python 中嵌套“WITH”语句的主要内容,如果未能解决你的问题,请参考以下文章

匹配 MongoDB 中嵌套子文档的嵌套数组

在 Gorilla Mux 中嵌套子路由器

VB 的 with 语句中语句能嵌套循环语句吗?比如for next

有没有办法在嵌套的 WITH 语句中包含 DELETE FROM 语句?

VBA - 在“IF语句”中嵌套“带语句”

[Unity工具]嵌套Prefab