I put a method in a file mymodule.py:
def do_something():
global a
a=1
If I try
>>> execfile('mymodule.py')
>>> do_something()
>>> print a
I get "1" as I expect. But if I import the module instead,
>>> from mymodule import *
and then run do_something(), then the python session knows nothing about the variable "a".
Can anyone explain the difference to me? Thanks.
execfile without globals, locals argument, It executes the file content in the current namespace. (the same namespace that call the execfile)
While, import execute the specified module in a separated namespace, and define the mymodule in the local namespace.
In the second part where you import mymodule, the reason why it isn't showing up is that a is global to the namespace of mymodule as done that way.
Try:
print mymodule.a
This prints:
1
As expected.
As per the Python documentation:
The global statement is a declaration which holds for the entire
current code block. It means that the listed identifiers are to be
interpreted as globals. It would be impossible to assign to a global
variable without global, although free variables may refer to globals
without being declared global.
Names listed in a global statement must not be used in the same code
block textually preceding that global statement.
Names listed in a global statement must not be defined as formal
parameters or in a for loop control target, class definition, function
definition, or import statement.
Related
I usually don't think too hard about variable scope in python, but I wanted to see if there's a clean explanation for this. Given two files called main.py and utils.py:
utils.py
def run():
print(L)
main.py
import utils
def run():
print(L)
if __name__ == '__main__':
L = [1,2]
run()
utils.run()
The first run() call in main.py runs fine despite L not being fed into run(), and the utils.run() call raises a NameError. Is L a global variable available to all functions defined in main.py?
If I imported utils with from utils import * instead of import utils, would that change anything?
It's module-level scope. A global variable defined in a module is available to all functions defined in the same module (if it's not overriden). Functions in another module don't have access to another module's variables unless they import them.
About "If I imported utils with from utils import * instead of import utils, would that change anything?":
No. The scope is determined at parsing time.
Check
this
for more information.
Notably:
It is important to realize that scopes are determined textually: the global
scope of a function defined in a module is that module’s namespace, no matter
from where or by what alias the function is called. On the other hand, the
actual search for names is done dynamically, at run time [...]
So the global scopes of both functions for variables defined in a module are the modules they're defined in. For one, its module also later has a definition for a global variable it uses, but not the other module, and when it's time to check for a variable when a function is run, each checks their own module's variables definitions, one finds it, the other does not.
See Python's FAQ. Their implementation of scope is a compromise between convenience and the dangers of globals.
Variables are treated as globals if they're only referenced by a function, and need to be explicitly declared as globals (e.g. global foo ) inside of the function body if you want to edit them. If you edit run() to try and change the value of L, you'll get an error.
What's happening here is that your Python code imports utils, and then runs run(). This function sees that you're looking for a variable named "L," and checks your global namespace.
I would like to clarify, how globals from different modules are scoped?
I failed to find relevant documentation for this matter, thus I am relying on observation, but I would like to have some more insight, if my findings are pure implementation coincidence, or if I can trust them?
Testcase:
module_1.py:
global_var1 = 'm1_v1'
global_var2 = 'm1_v2'
def f():
print('f: {}'.format(global_var1))
print('f: {}'.format(global_var2))
module_2.py:
import module_1
global_var1 = 'm2_v1'
def g():
print('g: {}'.format(global_var1))
print('g: {}'.format(global_var2))
module_1.f()
g()
$ python3 module_2.py
f: m1_v1
f: m1_v2
g: m2_v1
Traceback (most recent call last):
File "module_2.py", line 11, in <module>
g()
File "module_2.py", line 7, in g
print('g: {}'.format(global_var2))
NameError: name 'global_var2' is not defined
Conclusion:
Thus, my conclusion is that a function will use the globals in this order:
the module where the function is used
the module where the function is defined (EDIT: this is the only answer!)
Globals are not bleeding through from imported modules.
EDIT: Functions imported from other modules bring their module globals like a closure.
Question:
I would like to see some comprehensive documentation on this matter (which I failed to find...).
While testing this out is nice, I have no idea, if this is a freak coincidence, and this behavior should never be trusted, or this is the expected way?
Also, what if a function is somehow imported through a 3rd module? what if the function is a class method? Etc.etc.
If you can't point me to a documentation, but you know a guideline "for sure", I am interested, as well.
I won't go in lengths why and how I want to use this, I am primarily interested to better understand the workings of python. However, if you do know a better solution, given the information at hand, I am interested to see that, as well - it will NOT be accepted as an answer, though.
In case there is a difference between python2 and python3, my main interest is python3, but it is nice to have the info on python2, as well.
Each module has its own global scope. Let's look at the second module:
import module_1
global_var1 = 'm2_v1'
def g():
print('g: {}'.format(global_var1))
print('g: {}'.format(global_var2))
module_1.f()
g()
Since global_var1 and global_var2 aren't local variables, they are looked up in the global scope. Since module_2.global_var2 isn't defined, you get a NameError.
You would either need to create module_2.global_var2 with something like from module_1 import global_var2, or change the definition of g to
def g():
print('g: {}'.format(global_var1))
print('g: {}'.format(module_1.global_var2))
import module_1 only adds one name to the global scope of module_2, that being module_1, which refers to the module object created by the import statement. from module_1 import global_var2 also only adds one name, global_var2, which is initialized to the value of module1.global_var2 (though with the side effect of creating a new module). In this case, module1.global_var2 and module2.globar_var2 are two distinct objects, not two names for the same object.
TLDR: Python uses lexical/static scoping since Python 2.1, including Python 3. (See name resolution and PEP 227)
Lexical scoping means functions only have access to the enclosing scopes in which they are defined, up to their module’s global namespace. Only the builtins are visible in all modules. The global namespace of modules is not shared, and importing or calling a function in another module does not give it access to that namespace.
Some peculiarities worth pointing out:
Local/function scopes are defined when the function is parsed. Names are either local, closures/nonlocal, or global.
Global/module scopes are mutable. Names can be added, removed or changed at any time.
Classes introduce short-lived scopes that are not visible to functions or other classes defined inside them.
In the Python Guide's chapter on project structure, the term "top-level statement" is brought up a few times. I'm not sure exactly what this refers to. My guess is it's any variable declarations that happen outside of any functions or class methods that fire as soon as a module is loaded. Is this correct? Does it also include a module's import statements?
It's not just variable declarations (and there aren't any variable declarations anyway). It's pretty much anything that starts at indentation level 0.
import sys # top-level
3 + 4 # top-level
x = 0 # top-level
def f(): # top-level
import os # not top-level!
return 3 # not top-level
if x: # top-level
print 3 # not top-level
else:
print 4 # not top-level, but executes as part of an if statement
# that is top-level
class TopLevel(object): # top-level
x = 3 # not top-level, but executes as part of the class statement
def foo(self): # not top-level, but executes as part of the class statement
print 5 # not top-level
Here's the first mention of "top-level statement":
Once modu.py is found, the Python interpreter will execute the module in an isolated scope. Any top-level statement in modu.py will be executed, including other imports if any. Function and class definitions are stored in the module’s dictionary.
This makes it clear that what they really mean is "things that are interpreted at import time".
While it's not terribly helpful directly, the Python documentation itself also uses the phrase "top-level" (components, which then means "statements" in this context).
Note that this module:
"""a python module, spam.py"""
def spam():
return "spam"
class Spam(object):
pass
has two statements in it, the def and the class. These are both executed at import time. These definitions are compound statements (see def and class descriptions). If there are decorators attached to a top-level def, that adds even more top-level things to run. (See also user2357112's answer: running a class statement invokes more internal workings.)
Add an import sys at the top and you've added a third statement, which imports sys. However, if you add this:
def ham(eggs):
import os
return os.path.basename(eggs)
you have still only added one statement, the def ham, to the top-level stuff. It's when ham itself is executed (called) that the import os will be run.
In python, the statements which are not indented are called a top-level statement. Internally python gives a special name to top-level statement s as __main__.
Take the following code:
import something
def Foo():
something = something.SomeClass()
return something
…this is apparently not valid code:
UnboundLocalError: local variable 'something' referenced before assignment
…as the local variable something is created, but not assigned, before the RHS of the = is evaluated. (See, for example, this related answer's comment.) This seems a bit odd to me, but sure, I'll go with it. Now, why is the following valid code?
class Foo(object):
something = something.SomeClass()
My understanding was that the inside of a class definition was essentially a scope:
The class’s suite is then executed in a new execution frame (see section Naming and binding), using a newly created local namespace and the original global namespace.
So, then, why does that code act differently than that of a function?
From the python class documentation:
Class definitions place yet another namespace in the local scope.
A special quirk of Python is that – if no global statement is in effect – assignments to names always go into the innermost scope. Assignments do not copy data — they just bind names to objects. The same is true for deletions: the statement del x removes the binding of x from the namespace referenced by the local scope. In fact, all operations that introduce new names use the local scope: in particular, import statements and function definitions bind the module or function name in the local scope. (The global statement can be used to indicate that particular variables live in the global scope.)
So within a function (or a scope) the assignment creates a local unbound variable that is accessed before it is bound, whereas in a class definition it creates an entry in the "namespace" dictionary of that class on assignment, allowing the resolution of something to the outer namespace (the module namespace).
Consider the following example which may help to clarify this:
import datetime
class Foo(object):
datetime = datetime.datetime
>>> datetime
<module 'datetime' from '/usr/lib/python2.6/lib-dynload/datetime.so'>
>>> Foo.datetime
<type 'datetime.datetime'>
Note that the line datetime = datetime.datetime is actually assigning to the name Foo.datetime, which is not ambiguous with the global datetime (like it would be if the same code were in the function).
In summary, because class definitions create a new namespace as well as a new scope, you are allowed to directly access a name in an enclosing scope and assign to the same name in the local scope.
This question already has answers here:
Using global variables in a function
(25 answers)
Closed 8 months ago.
I'd like to be able to do something like this:
#mymodule
var = None
def load():
var = something()
Other module(s):
#secondmodule
import mymodule
mymodule.load()
#thirdmodule
from mymodule import var
print var #Shouldn't be None
But I don't know how to reference a modules variable from a function defined in the module.
Is this possible? Or am I going to need to put a global declaration in every place I wan't to use this.
Or am I going at this completely wrong?
Just change the function definition to:
def load():
global var # this line has been added to the original code
var = something()
Global variables are read-only from sibling methods. More accurately unless a variable is specified as global, Python consider it as local, but a read access to a local variable name will reach module-level scope if the name is not present in local scope.
See also use of “global” keyword in python and the doc for more details about the global statement
You seem to mostly have it. You are missing only the fact that "module-level" variables are called global in Python. (They are not truly global, but only global to the module they are declared in, in other words.)
In any function where you modify a global variable (you want to make the name refer to a different object), it must be declared global. So your load() function needs a global var at the beginning. If you are only using the value of a global variable, or if it is a mutable type such as a list and you are modifying it, but not changing the object that the name points to, you needn't declare it global.
The import statement is, as you have discovered, how you can import a module-level variable from one module into another.