Variable defined with with-statement available outside of with-block?
Yes, the context manager will be available outside the with statement and that is not implementation or version dependent. with statements do not create a new execution scope.
using python variable outside with statement
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
Scope of variable within with statement?
A with
statement does not create a scope (like if
, for
and while
do not create a scope either).
As a result, Python will analyze the code and see that you made an assignment in the with
statement, and thus that will make the variable local (to the real scope).
In Python variables do not need initialization in all code paths: as a programmer, you are responsible to make sure that a variable is assigned before it is used. This can result in shorter code: say for instance you know for sure that a list contains at least one element, then you can assign in a for
loop. In Java assignment in a for
loop is not considered safe (since it is possible that the body of the loop is never executed).
Initialization before the with
scope can be safer in the sense that after the with
statement we can safely assume that the variable exists. If on the other hand the variable should be assigned in the with
statement, not initializing it before the with
statement actually results in an additional check: Python will error if somehow the assignment was skipped in the with
statement.
A with statement is only used for context management purposes. It forces (by syntax) that the context you open in the with
is closed at the end of the indentation.
Is a variable defined in with open as block available for the code in outer block?
Yes, in Python, variable scope extends outside of blocks (with the exception of function and class blocks). This means you can do stuff like:
if True:
a = 1
a += 1
print(a) # 2
The same principle applies for with
blocks:
with open('data.txt') as file:
data = file.read()
print(data)
Note that if an exception is raised, the variable isn't assigned (but in your case, you already handle this with ktext = ""
in the except-block).
python - Variable scope after using a 'with' statement
Yes, in Python the scope of a variable ends only when the code block it's defined in ends, and the with
statement is not a code block per the documentation:
The following are blocks: a module, a function body, and a class
definition. Each command typed interactively is a block. A script file
(a file given as standard input to the interpreter or specified as a
command line argument to the interpreter) is a code block. A script
command (a command specified on the interpreter command line with the
‘-c’ option) is a code block. The string argument passed to the
built-in functions eval() and exec() is a code block.
Scope of variable in Python with statement
Python variables stay within scope until the end of the method. There are no 'blocks' for scope in python
Why is __del__ called at the end of a with block?
It's important to note that foo
is not an object of type Foo
. You do create a Foo
and need to keep it around because it might contain state information needed to call __exit__
. But once that's done, the object is unneeded and Python's free to throw it away.
Put another way, this:
with Foo() as foo:
print ('Hello World!')
Is the same as this:
_bar = Foo()
foo = _bar.__enter__()
print ('Hello World!')
_bar.__exit__()
del _bar # This will call __del__ because _bar is the only reference
The behavior you are expecting would happen if foo
were a reference to the with
block's foo. For example...
class Foo:
def __init__(self):
print ("__int__() called.")
def __del__(self):
print ("__del__() called.")
def __enter__(self):
print ("__enter__() called.")
return self # foo now stores the Foo() object
def __str__(self):
return 'returned_test_str'
def __exit__(self, exc, value, tb):
print ("__exit__() called.")
def close(self):
print ("close() called.")
def test(self):
print ("test() called.")
if __name__ == "__main__":
with Foo() as foo:
print ("with block begin???")
print ("with block end???")
print ("foo:", foo) # line 1
Prints
__int__() called.
__enter__() called.
with block begin???
with block end???
__exit__() called.
foo: returned_test_str
__del__() called.
I have no idea why Connection.__exit__
would leave its cursors open however.
Variable defined with with-statement available outside of with-block?
Yes, the context manager will be available outside the with statement and that is not implementation or version dependent. with statements do not create a new execution scope.
Related Topics
How to Leave/Exit/Deactivate a Python Virtualenv
When Should I Be Using Classes in Python
Reference Requirements.Txt for the Install_Requires Kwarg in Setuptools Setup.Py File
Integer Overflow in Numpy Arrays
Why Doesn't Django's Model.Save() Call Full_Clean()
Python: Tf-Idf-Cosine: to Find Document Similarity
How to Avoid "Permission Denied" When Using Pip with Virtualenv
How to Isolate Everything Inside of a Contour, Scale It, and Test the Similarity to an Image
How to Use Multiple Requests and Pass Items in Between Them in Scrapy Python
How to Implement Band-Pass Butterworth Filter with Scipy.Signal.Butter
Python Matplotlib Framework Under MACosx
Python: Sorting Items from Top Left to Bottom Right with Opencv
How to Remove Leading and Trailing Zeros in a String? Python
Sorting a 2D Numpy Array by Multiple Axes
Unicodeencodeerror: 'Ascii' Codec Can't Encode Character '\Xe9' - -When Using Urlib.Request Python3
Why Is the Empty Dictionary a Dangerous Default Value in Python