在Python中嵌套'WITH'语句
原来“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()
这样可以避免不必要的缩进。