Why doesn't "__all__" have desired effect for "import *"? - python

File structure:
./__init__.py
a.py
/lib
__init__.py
Foo1.py # contains `class Foo1`
Foo2.py # contains `class Foo2`
# so on ...
Tested this in a.py and worked, doing this;
from lib.Foo1 import Foo1
from lib.Foo2 import Foo2
But, when I do from lib import * the __all__ = ["Foo1", "Foo2"] in __init__.py it doesn't work.
Error: <type 'exceptions.TypeError'>: 'module' object is not callable
What I'm missing?
Here is a.py;
#!/usr/bin/python
import cgi, cgitb
cgitb.enable()
from lib import *
print "Content-Type: text/html"
print ""
print "Test!"
foo1 = Foo1()
foo2 = Foo2()
Used these refs:
http://docs.python.org/2/tutorial/modules.html#importing-from-a-package
How to load all modules in a folder?

from lib import *
Will import everything in lib to the current module, so our globals() looks like:
{'Foo1':<module lib.Foo1>,
'Foo2':<module lib.Foo2>}
Whereas
from lib.Foo1 import *
from lib.Foo2 import *
Makes our globals() become
{'Foo1':<class lib.Foo1.Foo1>,
'Foo2':<class lib.Foo2.Foo2>}
So in the first case we're just importing modules, not the classes inside them which is what we want.

When importing * from a package (as in your case, using the __all__ in init.py) __all__ specifies all modules that shall be loaded and imported into the current namespace.
So, in your case, from lib import * will import the modules Foo1 and Foo2 and you need to access the classes like so:
foo1 = Foo1.Foo1()
foo2 = Foo2.Foo2()
Have a look at Importing * in Python for a quick clarification.

Add the following to your .../lib/__init__.py file:
from Foo1 import Foo1
from Foo2 import Foo1
__all__ = ['Foo1', 'Foo2']
Note that PEP-8 recommends that package and modules names be all lowercase to avoid confusion.

Related

import modules from __init__.py in another folder

I have the following project structure:
- workflow/
file1.ipynb
file2.ipynb
...
- utils/
__init__.py
function_one.py
function_two.py
...
I am working on file1.ipynb, so far I have found a way to import the variables defined in init.py through the following code:
utils = importlib.machinery.SourceFileLoader('utils', '/home/utils/__init__.py').load_module()
Let's assume my __init__.py contains the following:
from .function_one import *
I can then use the variables defined inside the __init__.py file.
However, every time I want to call any of these variables I need to use the following syntax:
utils.function_one ...
I want to be able to write function_one without the utils at the beginning.
How can I import directly the variables defined inside the __init__.py ?
I don't know why you don't import your module with the normal import mechanism: from ..utils import * or depending on where your python interpreter was started just from utils import * but if you insist on using utils = importlib.machinery.SourceFileLoader('utils', '/home/utils/__init__.py').load_module() you can hack all values into your globals like this:
tmp = globals()
for attr_name in dir(utils):
if not attr_name.startswith("_"): # don't import private and dunder attributes
tmp[attr_name] = getattr(utils, attr_name)
del tmp
function_one(...) # should work now
Try this:
from ..utils import *

Importing the same Python object from the same file but from two different locations results in two different object types

I have a project organized in directories as follows:
|main_dir/
| /__init__.py
| /core/
| /__init__.py
| /foo.py
| /test1.py
| /scr/
| /test2.py
In foo.py, I define a class as follows
class foo(object):
def __init__(self):
pass
This is what I have in core/test1.py
from foo import foo
f1=foo()
print(type(f1))
This is what I have in scr/test2.py:
import sys
sys.path.append('../')
from core.foo import foo
f2 = foo()
print(type(f2))
main_dir/__init__.py contains this:
__all__ = ["core"]
import sys, os
dir = os.path.dirname(__file__)
for subpackage in __all__:
sys.path.append(os.path.join(dir,subpackage))
and core/__init__.py contains:
__all__ = ["foo"]
import sys, os
dir = os.path.dirname(__file__)
for subpackage in __all__:
sys.path.append(os.path.join(dir,subpackage))
When I run test1.py, the result is class 'foo.foo'> while when I run test2.py, I get <class 'core.foo.foo'>. I understand that this is how Python behaves, but I am not sure how to get around it. I would like to get True when checking type(f1) == type(f2) as I need to access the object foo for different locations.
Add the first two lines from test2.py:
import sys
sys.path.append('../')
to the top of test1.py. Then change your imports of foo in test1.py and test2.py to use the fully-qualified name:
from main_dir.core.foo import foo
Afterward:
# core/test.py
<class 'main_dir.core.foo.foo'>
# scr/test2.py
<class 'main_dir.core.foo.foo'>
I think in file core/test1.py You can try to import foo like this
from .foo import foo
with the dot before the file name to ensure that is the file in the same directory gave it a try
or
You can import foo using as like it down
from .foo import foo as foo_one
from core.foo import foo as foo_core
I hope I understand what do you need and I hope it will help

Python: A problem with the package import from ... import * using __all__ and __init__

I have the following Python package with 2 moludes:
-pack1
|-__init__
|-mod1.py
|-mod2.py
-import_test.py
with the code:
# in mod1.py
a = 1
and
# in mod2.py
from mod1 import a
b = 2
and the __init__ code:
# in __init__.py
__all__ = ['mod1', 'mod2']
Next, I am trying to import the package:
# in import_test.py
from pack1 import *
But I get an error:
ModuleNotFoundError: No module named 'mod1'
If I remove the dependency "from mod1 import a" in mod2.py, the import goes correctly. But that dependency makes the import incorrect with that exception "ModuleNotFoundError".
???
The issue here is that from mod2 perspective the first level in which it will search for a module is in the path from which you are importing it (here I am assuming that pack1 is not in your PYTHONPATH and that you are importing it from the same directory where pack1 is contained).
This means that if pack1 is in the directory /dir/to/pack1 and you do:
from mod1 import a
Python will look for mod1 in the same directory as pack1, i.e., /dir/to/pack1.
To solve your issue it is enough to do either:
from pack1.mod1 import a
or in Python 3.5+
from .mod1 import a
As a side note, unless this is a must for you, I do not recommend designing your package to be used as from pack import *, even if __all__ exists to give you better control of your public API.

Import a whole folder of python files

I am making a bot in python 3 and wish it to be easily expanded so I have a central file and then one for each command. I wish to know if there is a way to import a sub-directory full of modules without importing each separately. For example:
example
├── commands
│   ├── bar.py
│   └── foo.py
└── main.py
And the code in main.pywould be something like:
import /commands/*
Thanks :D
Solution:
Import each separately with:
from commands import foo, bar
from commands import * Does not work.
If you're using python3, the importlib module can be used to dynamically import modules. On python2.x, there is the __import__ function but I'm not very familiar with the semantics. As a quick example,
I have 2 files in the current directory
# a.py
name = "a"
and
# b.py
name = "b"
In the same directory, I have this
import glob
import importlib
for f in glob.iglob("*.py"):
if f.endswith("load.py"):
continue
mod_name = f.split(".")[0]
print ("importing {}".format(mod_name))
mod = importlib.import_module(mod_name, "")
print ("Imported {}. Name is {}".format(mod, mod.name))
This will print
importing b Imported <module 'b' from '/tmp/x/b.py'>.
Name is b
importing a Imported <module 'a' from '/tmp/x/a.py'>.
Name is a
Import each separately with:
from commands import bar and
from commands import foo
from commands import * Does not work.

Python Module issues

Im pretty new to python, and have been having a rough time learning it. I have a main file
import Tests
from Tests import CashAMDSale
CashAMDSale.AMDSale()
and CashAMDSale
import pyodbc
import DataFunctions
import automa
from DataFunctions import *
from automa.api import *
def AMDSale():
AMDInstance = DataFunctions.GetValidAMD()
And here is GetValidAMD
import pyodbc
def ValidAMD(GetValidAMD):
(short method talking to a database)
My error comes up on the line that has AMDInstance = DataFunctions.GetValidAMD()
I get the error AttributeError: 'module' object has no attribute 'GetValidAMD'
I have looked and looked for an answer, and nothing has worked. Any ideas? Thanks!
DataFunctions is a folder, which means it is a package and must contain an __init__.py file for python to recognise it as such.
when you import * from a package, you do not automatically import all it's modules. This is documented in the docs
so for your code to work, you either need to explicitly import the modules you need:
import DataFunctions.GetValidAMD
or you need to add the following to the __init__.py of DataFunctions:
__all__ = ["GetValidAMD"]
then you can import * from the package and everything listen in __all__ will be imported
When you create the file foo.py, you create a python module. When you do import foo, Python evaluates that file and places any variables, functions and classes it defines into a module object, which it assigns to the name foo.
# foo.py
x = 1
def foo():
print 'foo'
 
>>> import foo
>>> type(foo)
<type 'module'>
>>> foo.x
1
>>> foo.foo()
foo
When you create the directory bar with an __init__.py file, you create a python package. When you do import bar, Python evaluates the __init__.py file and places any variables, functions and classes it defines into a module object, which it assigns to the name bar.
# bar/__init__.py
y = 2
def bar():
print 'bar'
 
>>> import bar
>>> type(bar)
<type 'module'>
>>> bar.y
2
>>> bar.bar()
bar
When you create python modules inside a python package (that is, files ending with .py inside directory containing __init__.py), you must import these modules via this package:
>>> # place foo.py in bar/
>>> import foo
Traceback (most recent call last):
...
ImportError: No module named foo
>>> import bar.foo
>>> bar.foo.x
1
>>> bar.foo.foo()
foo
Now, assuming your project structure is:
main.py
DataFunctions/
__init__.py
CashAMDSale.py
def AMDSale(): ...
GetValidAMD.py
def ValidAMD(GetValidAMD): ...
your main script can import DataFunctions.CashAMDSale and use DataFunctions.CashAMDSale.AMDSale(), and import DataFunctions.GetValidAMD and use DataFunctions.GetValidAMD.ValidAMD().
Check out this.
It's the same problem. You are importing DataFunctions which is a module. I expct there to be a class called DataFunctions in that module which needs to be imported with
from DataFunctions import DataFunctions
...
AMDInstance = DataFunctions.GetValidAMD()

Categories