在with语句中覆盖文件引用变量

时间:2012-07-16 19:38:40

标签: python scope with-statement

如果这导致任何不良行为,我很好奇。我运行了一个测试用例并没有出现任何错误,所以我认为它没问题(虽然可能不是很好的做法)。只是想知道python如何处理我认为应该存在的问题?

with open("somefile.txt","r") as fileinfo:
    fileinfo = fileinfo.readlines()

print fileinfo

我认为覆盖“fileinfo”会导致问题退出with语句(引发一些关于无法使用.close()列表的错误)。 with语句是否保留文件引用的本地副本?谢谢!

2 个答案:

答案 0 :(得分:5)

当然,Python保留了对with语句中使用的对象的内部引用。否则,当您不使用as子句时,它会如何工作?

答案 1 :(得分:1)

with语句确实存储了对文件对象的本地引用(尽管我并不确切地知道self.gen中存储的内容)

查看主题,专门研究上下文管理器,发现这给了那些感兴趣的人更多细节。

class GeneratorContextManager(object):
    def __init__(self, gen):
        # Store local copy of "file reference"
        self.gen = gen

        def __enter__(self):
            try:
                return self.gen.next()
            except StopIteration:
                raise RuntimeError("generator didn't yield")

        def __exit__(self, type, value, traceback):
            if type is None:
                try:
                    self.gen.next()
                except StopIteration:
                    return
                else:
                    raise RuntimeError("generator didn't stop")
            else:
                try:
                    self.gen.throw(type, value, traceback)
                    raise RuntimeError("generator didn't stop after throw()")
                except StopIteration:
                    return True
                except:
                    # only re-raise if it's *not* the exception that was
                    # passed to throw(), because __exit__() must not raise
                    # an exception unless __exit__() itself failed.  But
                    # throw() has to raise the exception to signal
                    # propagation, so this fixes the impedance mismatch 
                    # between the throw() protocol and the __exit__()
                    # protocol.
                    #
                    if sys.exc_info()[1] is not value:
                        raise

def contextmanager(func):
    def helper(*args, **kwds):
        return GeneratorContextManager(func(*args, **kwds))
           return helper