Say I have a main module app.py which defines a global variable GLOBVAR = 123. Additionally this module imports a class bar located in another module foo:
from foo import bar
In the main module app I now call a method from the class bar. Within that method I want to access the value GLOBVAR from the main module app.
One straight-forward way would be to simply pass GLOBVAR to the method as parameter. But is there also another solution in Python that allows me to access GLOBVAR directly?
In module foo I tried one of the following:
from app import GLOBVAR # option 1
import app.GLOBVAR # option 2
However, both options lead to the following error at runtime:
ImportError: cannot import name bar
I understand this leads to a cyclic import between app and foo. So, is there a solution to this in Python, or do I have to pass the value as parameter to the function?
There are many ways to solve the same problem, and passing parameters is generally to be recommended. But if you do have some package wide global constants you can do that too. You will want to put these in a whole other module and import that module from both app and foo modules. If you build a package globals you can even put these in the __init__.py ... but another named module like settings or config can also be used.
For instance if you package layout is:
mypackage/
__init__.py
app.py
foo.py
config.py
Then:
config.py
GLOBVAR = 'something'
app.py
from mypackage.config import GLOBVAR
foo.py
from mypackage.config import GLOBVAR
if you just put the GLOBVAR in __init__.py then you would do from mypackage import GLOBVAR which could be prettier if you go for that sort of thing.
EDIT I'd also recommend using absolute imports even if you are using python 2, and always use the package name explicitly rather than relative imports for readability and because it makes things easier to split out later if you need to move something to a new different package
You can import a variable from the __main__ module like this:
""" main module """
import foo
name = "Joe"
foo.say_hi()
and foo.py:
""" foo module, to be imported from __main__ """
import __main__
def say_hi():
print "Hi, %s!" % __main__.name
and it looks like this:
$ python main.py
Hi, Joe!
Of course you can not access the variable before you define it. So you may need to put the access to __main__.name at function level, where it is evaluated after the import. In contrast to the module level, which is evaluated at the time of the import (where the variable not yet exists).
You should just write import line before where you want to use GLOBVAR this will prevent cycle!
In foo.py, the line
from app import GLOBVAR
must be after the bar class definition.
You can put GLOBVAR in a third module, import it into foo, and inside app import it from foo.
glob.py:
GLOBVAR=None
foo.py:
class bar:
global GLOBVAR
from glob.py import GLOBVAR
app.py:
from foo import GLOBVAR
import foo
Related
I have the following situation:
The first file, named a.py contains:
var = 2
The second file, named b.py contains:
def prnt():
print(var)
The third file, named c.py contains:
from a import *
from b import *
prnt() # NameError: name 'var' is not defined
and raises the given error. I always thought that the import statement basically "copies" code into the calling namespace, so it should be the same as:
var = 2
def prnt():
print(var)
prnt()
but apparently this is not the case. What am I missing?
When you import a module, the code in that module is run by the interpreter (see this for example; add a print statement in there and you'll see it in action). Therefore you can't use variables etc without defining them or importing them.
In b.py do this at the top:
from a import var
Then, unless you need var in c.py, you won't need to import anything from a.py in c.py.
I know this is fake code, but avoid using globals in your functions.
Given a module mymodule with an __init__.py file how can I define a functions of mymodule from another function within that file?
__init__.py code outline:
def a():
THISMODULE.__dict__["b"] = lambda: print("this is not weird")
a()
b() # Expect "this is not weird" output
mymodule comes as a replacement for anothermodule and I want to make the code change as simple as replacing import anothermodule as thething with import mymodule as thething. Since I don't implement all the functions of anothermodule just yet, I would like to send the user a notification about it instead of crashing with "not defined".
__name__ is a module attribute set by the import machinery, which evaluates to the name of the current module. Adding this to the top of your file:
import sys
THISMODULE = sys.modules[__name__]
And the rest of what you already have should work correctly.
Dir structure:
main.py
my_modules/
module1.py
module2.py
module1.py:
class fooBar():
....
class pew_pew_FooBarr()
....
...
How can I add all classes from module* to main without prefixes (i.e. to use them like foo = fooBar(), not foo = my_modules.module1.fooBar()).
An obvious decision is to write in main.py something like this:
from my_modules.module1 import *
from my_modules.module2 import *
from my_modules.module3 import *
...
But I don't want to change main.py when I create new moduleN. Is there solution for that?
I do know it's not a good idea to import classes like this, but I'm still curious about that.
UPD: This question differs from this one Loading all modules in a folder in Python, because my problem is to load modules without namespaces.
In the my_modules folder, add a __init__.py file to make it a proper package. In that file, you can inject the globals of each of those modules in the global scope of the __init__.py file, which makes them available as your module is imported (after you've also added the name of the global to the __all__ variable):
__all__ = []
import pkgutil
import inspect
for loader, name, is_pkg in pkgutil.walk_packages(__path__):
module = loader.find_module(name).load_module(name)
for name, value in inspect.getmembers(module):
if name.startswith('__'):
continue
globals()[name] = value
__all__.append(name)
Now, instead of doing:
from my_modules.class1 import Stuff
You can just do:
from my_modules import Stuff
Or to import everything into the global scope, which seems to be what you want to do:
from my_modules import *
The problem with this approach is classes overwrite one another, so if two modules provide Foo, you'll only be able to use the one that was imported last.
So i'm reading Alex Martelli's answer to other question...
"One example in which I may want initialization is when at package-load time I want to read in a bunch of data once and for all (from files, a DB, or the web, say) -- in which case it's much nicer to put that reading in a private function in the package's init.py rather than have a separate "initialization module" and redundantly import that module from every single real module in the package..."
Unfortunately, when i try this:
foo/__init__.py
import tables as tb
global foo
foo = tb.openFile('foo.h5', etc._)
import bar
foo/bar/__init__.py
import tables as tb
global bar
bar = foo.createGroup('/', bar)
import MyFunction`
foo/bar/MyFunction.py
def MyFunction(*of foo and bar*):
'...'
>>> import foo
>>> OUTPUT= foo.bar.MyFunction.MyFunction(INPUT)
>>> bar = foo.createGroup('/', bar)
NameError: name 'foo' is not defined
How does one define global variables without putting them in a function (as seen here)?
global variables are not global in the sense that every bit of python code sees the same set of globals. the global-ness is really just the 'module scope'; All of the variables and functions defined in a module are already global, and as global as they can possibly be.
If you want to see the variables defined in one module among the globals of another module, the only way to do it is to import the names of the first module into the second... IE:
# myModule.py
foo = "bar"
# yourModule.py
from myModule import foo
I have two modules, a.py and b.py. I want the globals from a.py to be available in b.py like this:
a.py:
#!/usr/bin/env python
var = "this is global"
import b
b.foo()
b.py:
#!/usr/bin/env python
var = "this is global"
def foo():
print var
Currently, I re-declare the globals in each module. There must be an easier way.
Create a settings module that has shared globals if that's what you want. That way you're only importing and referencing each global one time, and you're keeping them isolated within the namespace of the settings module. It's a good thing.
#settings.py
var = 'this is global'
# a.py
import settings
import b
b.foo()
# b.py
import settings
def foo():
print settings.var
By making b.py require globals from a.py, you have created classes that depend on each other, which is bad design.
If you have static variables that need to be shared, consider creating c.py which both a.py and b.py can import and reference.
If you have dynamic variables that need to be shared, consider creating a settings class that can be instantiated and passed between the modules.
Define your globals in c.py and import them into a.py and b.py