Matthias
Matthias

Reputation: 10379

Python: How to access a variable in calling module?

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

Answers (5)

moooeeeep
moooeeeep

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

underrun
underrun

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

Elazar
Elazar

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

Janne Karila
Janne Karila

Reputation: 25197

In foo.py, the line

from app import GLOBVAR

must be after the bar class definition.

Upvotes: 1

Aryan
Aryan

Reputation: 2735

You should just write import line before where you want to use GLOBVAR this will prevent cycle!

Upvotes: 1

Related Questions