Question

I was curious if this causes any bad behaviors. I ran a test case and got no errors so I assume its OK (although probably not good practice). Just wanted to know how python deals with the issue I assumed should have existed?

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

print fileinfo

I thought overwritting "fileinfo" would cause issues exiting the with statement (raise some error about not being able to .close() a list). Does the with statement retain a local copy of the file reference? Thanks!

Was it helpful?

Solution

Of course Python retains an internal reference to the object used in the with statement. Otherwise how would it work when you don't use the as clause?

OTHER TIPS

A with statement does indeed store a local reference to the file object (although I am not positive exactly what is stored in self.gen)

Looked into the topic, specifically researching the context manager and found this which gives slightly more detail for those interested.

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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top