【问题标题】:Nesting 'WITH' statements in Python在 Python 中嵌套“WITH”语句
【发布时间】: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 语句是不可以的,但如果知道更多的人有不同的意见,我很乐意听到。

【问题讨论】:

    标签: python append with-statement


    【解决方案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 年历史了)
        猜你喜欢
        • 2018-12-06
        • 1970-01-01
        • 2021-08-29
        • 2020-12-13
        • 2010-10-16
        • 2021-10-26
        • 1970-01-01
        • 1970-01-01
        • 2019-08-28
        相关资源
        最近更新 更多