I have a problem with globals using method of class from my testmodule
Example: Text of my test module:
cat ./testmodule.py
class testclass(object): def __init__(self): self.testfunc() def testfunc(self): print(' '.join(globals()).split(' '))
Text of my test class the same:
class testclass(object): def __init__(self): self.testfunc() def testfunc(self): print(' '.join(globals()).split(' '))
Text of my test func, nothing new:
def testfunc(): print(' '.join(globals()).split(' '))
And go to test it.
Python 3.6.6 (default, Aug 13 2018, 18:24:23) [GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux Type "help", "copyright", "credits" or "license" for more information. >>> >>> >>> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa='a' >>> >>> import testmodule >>> >>> class testclass(object): ... def __init__(self): ... self.testfunc() ... ... def testfunc(self): ... print(' '.join(globals()).split(' ')) ... >>> def testfunc(): ... print(' '.join(globals()).split(' '))
Everything is ready, let’s test
>>> testfunc() ['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__annotations__', '__builtins__', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'testmodule', 'testclass', 'testfunc']
Variable exist
>>> testclass.testfunc(testclass) ['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__annotations__', '__builtins__', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'testmodule', 'testclass', 'testfunc']
The same result, variable exist
>>> testmodule.testclass.testfunc(testclass) ['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__file__', '__cached__', '__builtins__', 'testclass'] >>>
Variable is lost.
How can i get the same result from testmodule like from testclass and testfunc?
Advertisement
Answer
Expanding on @chepner’s comment: globals()
returns the module-level variables of the current module only.
- When you define
testfunc()
in the REPL, it is defined as__main__.testfunc
and invokingglobals()
returns essentially__main__.__dict__
. - When defined in your
testmodule
, it is defined astestmodule.testfunc
andglobals()
returnstestmodule.__dict__
.
If you want testfunction
to access globals of another module, you need to ensure that globals()
is called in the lexical scope of the module. The easiest was is to extend testfunction
to expect a dictionary as argument:
## testmodule.py def testfunc(globals_): print(globals) ## REPL or other module import testmodule testmodule.testfunc(globals())
Additional details
__main__
isn’t defined by default. You need toimport __main__
before you can use it. But you can see that the current module is named__main__
from the variable__name__
.- When you run
python somescript.py
, the contents of the file are executed as the__main__
module, not as asomescript
module. Python has closures, and functions inside modules behave essentially like closures over the module scope – so I would have expected
globals()
to be a member of every module. Then the following would have yielded the expected result:%% testmodule.py def testfunc(globals_): print(_globals()) %% REPL import testmodule testmodule.testfunc(globals)
but again, this returns the globals of only the testmodule. Instead
globals
is defined only in__builtin__
, and seems to use the scope of the caller as hidden argument. As a consequence:## REPL import testmodule testmodule.testfunc(globals) # prints testmodule.__dict__ testmodule.testfunc(lambda: globals()) # prints __main__.__dict__
Normally expect
f
andlambda: f()
to have the same result.You can’t rely on
somemodule.__dict__
to be defined. A module may actually choose to return some wrapper object instead of a normal module object, when you import it. Actually, nothing even enforces thatsomemodule
has typical module semantics! E.g. try the module:## somemodule.py -- Please don't actually do this. import sys sys.modules["somemodule"] = "not a module" ## REPL >>> import somemodule >>> somemodule 'not a module'
A real-world example for such changes would be
os.path
:>>> import os.path >>> os.path <module 'ntpath' from 'C:toolsmsys64mingw64libpython2.7ntpath.pyc'>