How to share globals between imported modules? - python

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

Related

How to import dependent code from two modules?

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.

how do imports work for a module used as a singleton?

I'm confused about what happens if you tread a module as a singleton.
Say I have a module conf.py, that contains some configuration parameters which need to be accessed by multiple other files. In conf.py, I might have this piece of code (and nothing else):
myOption = 'foo' + 'bar'
If I now import it first in a.py, and then in b.py, my understanding is that the first time it is imported (in a.py), the string concatenation will be executed. But the second time it is imported (in b.py), conf.myOption already has its value, so no string concatenation will be executed. Is this correct?
If after doing these two imports, I then execute the following in b.py
conf.myOption = 'aDifferentFoobar'
then obviously b.py would now see this new value. Would a.py see the same value, or would it still see 'foobar'?
I believe (but correct me if I'm wrong) that imports are always referred to by reference, not by value? And I'm guessing that's what the above questions boil down to.
Try it and see:
mod.py:
def foo():
print("in foo()")
return "foo"
bar = foo()
opt = "initial"
b.py:
import mod
mod.opt = "changed"
a.py:
import mod
import b
print(mod.bar)
print(mod.opt)
Execute a.py:
$ python3.4 a.py
Output:
in foo()
foo
changed
We learn:
foo() is only executed once
mod.opt is changed by b.py
a.py sees the changed value of mod.opt
bonus: the order of imports in a.py does not matter

Calling isinstance in main Python module

There is a strange behavior of isinstance if used in __main__ space.
Consider the following code
a.py:
class A(object):
pass
if __name__ == "__main__":
from b import B
b = B()
print(isinstance(b, A))
b.py
from a import A
class B(A):
pass
main.py
from a import A
from b import B
b = B()
print(isinstance(b, A))
When I run main.py, I get True, as expected, but when I run a.py, I am getting False. It looks like the name of A is getting the prefix __main__ there.
How can I get a consistent behavior?
I need this trick with import of B in a.py to run doctest on file a.py.
WSo what happens when you run a.py is that Python reads a.py and executes it. While doing so, it imports module b, which imports module a, but it does not reuse the definitions from parsing it earlier. So now you have two copies of the definitions inside a.py, known as modules __main__ and a and thus different __main__.A and a.A.
In general you should avoid importing modules that you are executing as well. Rather you can create a new file for running doctests and use something like
import a
import doctest
doctest.testmod(a)
and remove the __main__ part from module a.
Chain of events:
The a.py script is called.
The class A statement is executed, creating A in the __main__
namespace.
b is imported.
In b.py a is imported.
The class A statement is executed, creating A in the a namespace.
This A in the a namespace has no relation to the A in the
__main__ namespace other than having been generated by the same
code. They are different objects.
I agree with Helmut that it is best to avoid such circular imports. However, if you wish to fix your code with minimal changes, you could do the following:
Let's rename b.py --> bmodule.py so we can distinguish b the module from b the variable (hopefully in your real code these names are already distinct):
class A(object):
pass
if __name__ == "__main__":
import bmodule
b = bmodule.B()
print(isinstance(b, bmodule.A))
prints
True

Python Etiquette: Importing Modules

Say I have two Python modules:
module1.py:
import module2
def myFunct(): print "called from module1"
module2.py:
def myFunct(): print "called from module2"
def someFunct(): print "also called from module2"
If I import module1, is it better etiquette to re-import module2, or just refer to it as module1.module2?
For example (someotherfile.py):
import module1
module1.myFunct() # prints "called from module1"
module1.module2.myFunct() # prints "called from module2"
I can also do this: module2 = module1.module2. Now, I can directly call module2.myFunct().
However, I can change module1.py to:
from module2 import *
def myFunct(): print "called from module1"
Now, in someotherfile.py, I can do this:
import module1
module1.myFunct() # prints "called from module1"; overrides module2
module1.someFunct() # prints "also called from module2"
Also, by importing *, help('module1') shows all of the functions from module2.
On the other hand, (assuming module1.py uses import module2), I can do:
someotherfile.py:
import module1, module2
module1.myFunct() # prints "called from module1"
module2.myFunct() # prints "called from module2"
Again, which is better etiquette and practice? To import module2 again, or to just refer to module1's importation?
Quoting the PEP 8 style guide:
When importing a class from a class-containing module, it's usually okay to spell this:
from myclass import MyClass
from foo.bar.yourclass import YourClass
If this spelling causes local name clashes, then spell them
import myclass
import foo.bar.yourclass
Emphasis mine.
Don't use module1.module2; you are relying on the internal implementation details of module1, which may later change what imports it is using. You can import module2 directly, so do so unless otherwise documented by the module author.
You can use the __all__ convention to limit what is imported from a module with from modulename import *; the help() command honours that list as well. Listing the names you explicitly export in __all__ helps clean up the help() text presentation:
The public names defined by a module are determined by checking the module’s namespace for a variable named __all__; if defined, it must be a sequence of strings which are names defined or imported by that module. The names given in __all__ are all considered public and are required to exist. If __all__ is not defined, the set of public names includes all names found in the module’s namespace which do not begin with an underscore character ('_'). __all__ should contain the entire public API. It is intended to avoid accidentally exporting items that are not part of the API (such as library modules which were imported and used within the module).
Just import module2. Re-importing is relatively costless, since Python caches module objects in sys.modules.
Moreover, chaining dots as in module1.module2.myFunct is a violation of the Law of Demeter. Perhaps some day you will want to replace module1 with some other module module1a which does not import module2. By using import module2, you will avoid having to rewrite all occurrences of module1.module2.myFunct.
from module2 import * is generally a bad practice since it makes it hard to trace where variables come from. And mixing module namespaces can create variable-name conflicts. For example, from numpy import * is a definite no-no, since doing so would override Python's builtin sum, min, max, any, all, abs and round.

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?
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

Categories

Resources