28

In a Python script, I encountered a variable that was defined inside a with statement, but that was used outside the statement, like file in the following example:

with open(fname, 'r') as file:
    pass
print(file.mode)

Intuitively I would say that file should not exist outside the with statement and that this only works by accident. I could not find a conclusive statement in the Python documentation on whether this should work or not though. Is this type of statement safe for use (also for future python versions), or should it be avoided? A pointer to this information in the Python docs would be very helpful as well.

5
  • 2
    The code you posted shouldn't work. Leaving the context manager (the with block) will close the file. I stand corrected. See comments below. Commented Jun 8, 2017 at 13:55
  • @WillDaSilva have you tried it? It works for me in Python 2.7 Commented Jun 8, 2017 at 13:56
  • 5
    It does work as file.mode does not access the file itself, just the Python object. Commented Jun 8, 2017 at 13:56
  • 3
    with blocks do not create a new scope. All references are created in the local scope. Same for loops etc., which is why after for i in range(5):, i is still available. The with block will close the file handle. Commented Jun 8, 2017 at 13:58
  • 2
    yes, file will be closed. But object that represent closed file is still available, as print() call is in same scope as with statement. Commented Jun 8, 2017 at 14:02

1 Answer 1

25

Variable scope only applies at the function, module, and class levels. If you are in the same function/module/class, all variables defined will be available within that function/module/class, regardless of whether it was defined within a with, for, if, etc. block.

For example, this:

for x in range(1):
    y = 1
print(y)

is just as valid (although pointless) as your example using the with statement.

However, you must be careful since the variable defined within your code block might not actually be defined if the block is never entered, as in this case:

try:
    with open('filedoesnotexist', 'r') as file:
        pass
except:
    pass # just to emphasize point

print(file.mode)

Traceback (most recent call last):
  File "<pyshell#43>", line 1, in <module>
    file.mode
NameError: name 'file' is not defined

Good description of LEGB rule of thumb for variable scope

Sign up to request clarification or add additional context in comments.

2 Comments

I made a context manager and the user is able to use the with clause variable outside the with block. with Database() as db: #do something then using variable db outside the with block
I think variable scope also applies to list comprehensions, set comprehensions, dict comprehensions and generator expressions. ISTR that list comprehensions leaked variables in Python 2.x.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.