Reputation: 10379
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?
Upvotes: 2
Views: 3479
Reputation: 32502
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).
Upvotes: 2
Reputation: 6841
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
Upvotes: 4
Reputation: 21595
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
Upvotes: 1
Reputation: 25197
In foo.py, the line
from app import GLOBVAR
must be after the bar
class definition.
Upvotes: 1
Reputation: 2735
You should just write import line before where you want to use GLOBVAR this will prevent cycle!
Upvotes: 1