Import a single global variable from a different module in python - python

I have an interesting application and I would like to access a global variable from a different module.
I currently have module x
from pkg.mod import *
in order to get the namespace foo.
where my pkg.mod looks like the following
import x
foo = 0
# do some stuff
foo = myClass()
That all works just great, however, I would like NOT to do that, mostly just because its bad.
If I try the following
from pkg import mod
I get a circular dependency issue. ImportError: cannot import name mod which makes sense to me.
What I want to do is
from pkg.mod import foo
but that also gives me an import name error: ImportError: cannot import name foo
Which I am not exactly sure why, except I dont think you can import variables specifically.
Is there anyway to import foo following correct practices?
---edit---
I have tried to remove the shared variable and put it in a third module in such a way
pkg.y
foo = 0
pkg.mod
from pkg.y import foo
foo = myClass()
x.dostuff()
x
from pkg.y import foo
def dostuff():
print(foo)
and now x thinks foo is still 0. (I can guarantee that mod is calling x, and thus happening first.)

When I need a true global variable I find it cleaner to create a module called trueglobals.py; it can remain empty but for proper documentation...
# -*- coding: utf-8 -*-
# Object references that are used extensively across many modules are
# stored here.
# someObject1 - instantiated in main.py
# someObject2 - instantiated in someothermodule.py
In the module instantiating the object...
import trueglobals
trueglobals.someObject1 = myClass(somevar)
In any module requiring the object...
import trueglobals
localVar = trueglobals.someObject1

Related

Python custom module name not defined

I have a custom package called 'package' and a custom module in that package called 'module' which has a function returning 'test' when called. When I import my package if I do:
from package import module
Everything works fine but if I do:
from package import *
Or
import package
Then when trying to use the 'module' module it comes up with an error name 'module' is not defined. Why is it not importing the module when I use import * or when I import the package?
The code in the module I am trying to call is this:
def printTest():
return("Test")
The code in the file calling the module is this:
import package
print(module.printTest())
This is a surprisingly common issue and this question was still without an proper answer, so here we go.
Let's suppose we have a module only with functions inside, say:
file app/foo.py:
def a():
print('Hello from foo.a')
def b():
print('Hello from foo.b')
I would genuinely expect this to work (but it DOESN'T):
file app/bar.py:
import app.foo
# These will not work!
foo.a()
foo.b()
It turns out that you have to import each element explicitly or give app.foo a name:
Import everything (usually considered a bad practice):
from app.foo import *
# Both will work fine
a()
b()
Import only what you want:
from app.foo import b
# This will work
b()
# But this will not
a()
Give app.foo a (nice) name:
import app.foo as baz
# Both will work as expected
baz.a()
baz.b()
Even if the examples above use only functions, it works exactly the same for everything declared at the top most scope of the module, like classes or variables.
Hope it helps!
If you just want to execute the script outside the original file, you can try:
exec(open('filename').read())
it may be more suitable than using import?
I was facing the same issue, turns out that the file that I wanted to import has the name in lowercase like this global.py once I changed it to Global.py and added
import Global as glb
in main.py (the file where I wanted to import) everything worked as expected.

Class definition from shelve

I'm using python 3.5. Fairly new to python but not new to programming. I have three source files as follows (a much simplified version of what I'm actually doing):
c.py
class C:
def __init__(self, x):
self.x = x
def method(self):
print(self.x)
init.py
import shelve
from c import C
db = shelve.open("DB")
db['key1'] = C("test")
db.close()
test.py
import shelve
db = shelve.open("DB")
obj = db['key1']
obj.method() # this works
C.method(obj) # this doesn't -- 'C' not defined
db.close()
So I run init.py to set up my shelved database. Then I run test.py. It is happy with executing obj.method(), so it seems to know about class C even though I haven't explicitly imported it (Lutz says something about it being stored in the database). But if I try to do C.method(obj) (not that I'd necesarily need to call it this way, but using C as a class (for example to create new objects) has its usefulness) it says 'C' is not defined. But if I add 'from c import C' to test.py then it works. So in one way it seems to know about C's definition, but then again it doesn't. I am curious to know why this is.
When shelve serializes an object (I believe by pickling it), it stores the import path to the class for unpickling later. When it retrieves the object, pickle imports the module (c) and returns an instance of C back to you (that is equivalent to the one that was originally serialized).
So far, this isn't anything new to you based on your observations. However, when it imports c, it doesn't import it into your current namespace. In fact, it imports it into a very localized namespace. So while the c module has been imported (you can find it in sys.modules), you won't find c or C in your current namespace because you haven't imported it there.
Put another way, simply importing something doesn't make it accessible to every module in your program. It only makes it accessible to the module (actually scope) where it was imported. I can import os, but just because os imports sys doesn't mean that I immediately have access to sys. I need to import it too before I can start using it.
>>> import os
>>> sys
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'sys' is not defined
>>> os.sys
<module 'sys' (built-in)>
>>> import sys
>>> sys
<module 'sys' (built-in)>
What you have doesn't work for the reasons stated in mgilson's answer.
A work-around for the problem would be to manually import the class from the module and assign the class to the name C — something along these lines (tested with Python 3.5.1):
import shelve
db = shelve.open("DB")
obj = db['key1']
obj.method() # this works
## Begin added code ##
classname = obj.__class__.__name__
module_name = obj.__module__
module = __import__(module_name, globals(), locals(), [classname], 0)
globals()[classname] = getattr(module, classname)
## Added code end ##
C.method(obj) # this also works now
db.close()

Why can't Python's import work like C's #include?

I've literally been trying to understand Python imports for about a year now, and I've all but given up programming in Python because it just seems too obfuscated. I come from a C background, and I assumed that import worked like #include, yet if I try to import something, I invariably get errors.
If I have two files like this:
foo.py:
a = 1
bar.py:
import foo
print foo.a
input()
WHY do I need to reference the module name? Why not just be able to write import foo, print a? What is the point of this confusion? Why not just run the code and have stuff defined for you as if you wrote it in one big file? Why can't it work like C's #include directive where it basically copies and pastes your code? I don't have import problems in C.
To do what you want, you can use (not recommended, read further for explanation):
from foo import *
This will import everything to your current namespace, and you will be able to call print a.
However, the issue with this approach is the following. Consider the case when you have two modules, moduleA and moduleB, each having a function named GetSomeValue().
When you do:
from moduleA import *
from moduleB import *
you have a namespace resolution issue*, because what function are you actually calling with GetSomeValue(), the moduleA.GetSomeValue() or the moduleB.GetSomeValue()?
In addition to this, you can use the Import As feature:
from moduleA import GetSomeValue as AGetSomeValue
from moduleB import GetSomeValue as BGetSomeValue
Or
import moduleA.GetSomeValue as AGetSomeValue
import moduleB.GetSomeValue as BGetSomeValue
This approach resolves the conflict manually.
I am sure you can appreciate from these examples the need for explicit referencing.
* Python has its namespace resolution mechanisms, this is just a simplification for the purpose of the explanation.
Imagine you have your a function in your module which chooses some object from a list:
def choice(somelist):
...
Now imagine further that, either in that function or elsewhere in your module, you are using randint from the random library:
a = randint(1, x)
Therefore we
import random
You suggestion, that this does what is now accessed by from random import *, means that we now have two different functions called choice, as random includes one too. Only one will be accessible, but you have introduced ambiguity as to what choice() actually refers to elsewhere in your code.
This is why it is bad practice to import everything; either import what you need:
from random import randint
...
a = randint(1, x)
or the whole module:
import random
...
a = random.randint(1, x)
This has two benefits:
You minimise the risks of overlapping names (now and in future additions to your imported modules); and
When someone else reads your code, they can easily see where external functions come from.
There are a few good reasons. The module provides a sort of namespace for the objects in it, which allows you to use simple names without fear of collisions -- coming from a C background you have surely seen libraries with long, ugly function names to avoid colliding with anybody else.
Also, modules themselves are also objects. When a module is imported in more than one place in a python program, each actually gets the same reference. That way, changing foo.a changes it for everybody, not just the local module. This is in contrast to C where including a header is basically a copy+paste operation into the source file (obviously you can still share variables, but the mechanism is a bit different).
As mentioned, you can say from foo import * or better from foo import a, but understand that the underlying behavior is actually different, because you are taking a and binding it to your local module.
If you use something often, you can always use the from syntax to import it directly, or you can rename the module to something shorter, for example
import itertools as it
When you do import foo, a new module is created inside the current namespace named foo.
So, to use anything inside foo; you have to address it via the module.
However, if you use from from foo import something, you don't have use to prepend the module name, since it will load something from the module and assign to it the name something. (Not a recommended practice)
import importlib
# works like C's #include, you always call it with include(<path>, __name__)
def include(file, module_name):
spec = importlib.util.spec_from_file_location(module_name, file)
mod = importlib.util.module_from_spec(spec)
# spec.loader.exec_module(mod)
o = spec.loader.get_code(module_name)
exec(o, globals())
For example:
#### file a.py ####
a = 1
#### file b.py ####
b = 2
if __name__ == "__main__":
print("Hi, this is b.py")
#### file main.py ####
# assuming you have `include` in scope
include("a.py", __name__)
print(a)
include("b.py", __name__)
print(b)
the output will be:
1
Hi, this is b.py
2

Is there a way to bypass the namespace/module name in Python?

If you have a module like module, can you bypass it and use the functions available inside without using the module?
I imported the module, but the compiler still complains not having to find function. I still have to use module.function().
It has many more functions, so I don't want to redefine them one by one but just avoid typing module if possible.
Importing in Python just adds stuff to your namespace. How you qualify imported names is the difference between import foo and from foo import bar.
In the first case, you would only import the module name foo, and that's how you would reach anything in it, which is why you need to do foo.bar(). The second case, you explicitly import only bar, and now you can call it thus: bar().
from foo import * will import all importable names (those defined in a special variable __all__) into the current namespace. This, although works - is not recommend because you may end up accidentally overwriting an existing name.
foo = 42
from bar import * # bar contains a `foo`
print foo # whatever is from `bar`
The best practice is to import whatever you need:
from foo import a,b,c,d,e,f,g
Or you can alias the name
import foo as imported_foo
Bottom line - try to avoid from foo import *.

Python: Can i set global variables in a package __init__ module?

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

Categories

Resources