2

I was reading a question in StackOverflow where the user applied the "with" statement twice in a row, pipelining the results from a variable declared inside the first with statement into the second. Like so (simple example):

with open('first_file.txt', 'r') as f:
   loaded_file = f.readlines()
   #...Prepare a csv file somehow - loaded_file is not declared outside with...

with open("second_file.csv", "w") as f:
   for line in loaded_file:
      f.write(line+"\n")

Considering variable scopes, why does it work?

2 Answers 2

3

Only one statement creates a new scope: the def statement. Any other assignment creates a name that is local to the current function body.

The exceptions are:

  • A name declared global refers to the (module) global scope rather than the local function body.
  • A name declared nonlocal refers to the name defined in the closest containing function scope (or global scope if no other name is found)
  • The Python interpreter itself can define names.

In your example, f is either a local variable or a global, depending on the scope where the with statement occurs. In no way is f local to any other particular statement.

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

1 Comment

Excelent addition. Provides further generalization to the answer.
3

No, "with" statements does not create a new scope.

The "With" statement is a resource developed by the Python Dev team to generalize a common (and heavily recommended) practice of closing opened resources even after an exception ocurred. Imagine the following situation:

try:
   f = open('file.txt', 'w')
   #Do some processing that can raise exceptions and leave 'f' open, eventually locking the file or having trash data loaded into RAM.
   #To avoid this situation, a mindful developer will do the following:
finally:
   f.close()

It gets verbose easily.

To solve the problem, python dev team proposed the use of some dunder methods which encapsule this process: __enter__() and __exit__() - these are invoked "under the hood" when you use a "with" statement.

You can even implement them in your own classes!

class controlled_execution:
    def __enter__(self):
        set things up
        return thing
    def __exit__(self, type, value, traceback):
        tear things down
with controlled_execution() as thing:
    some code

In the end, a with statement, even though there's identation, is not a separate block of code. It is just an ellegant try...finaly block. It abstracts a "contained" piece of code.

This can be easily comprehended by looking at a try...except statement with variables declared inside the try:

x = 10
try:
    y = load_using_failable_function()
    z = 5
except FunctionFailureException:
    y = 10
#If you treat it properly, there's nothing wrong with doing:
x = x + y + z

I hope it is clear to anyone else looking for this reason.

Consulted websites:

https://www.geeksforgeeks.org/with-statement-in-python/

https://effbot.org/zone/python-with-statement.htm

1 Comment

Can you please add an answer "yes" or "not" to the question in the title "Are variables declared inside "with" statement local?"

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.