I've been trying to understand how importing packages and subpackages works in Python. Based on what I understood from realpython.com, a package is simply a directory that contains python modules and a __init__.py
file in which you could include an __all__
list object containing all the objects to import should you use an import *
statement. On top of that, if you want to include more subpackages, each one should be a subdirectory with a __init__.py
file in it.
So, let's assume I'm working on a project that looks something like this where my_pckg/
is a package I'm trying to create.
Project/
├── main.py
└── my_pckg/
├── __init__.py
├── functions.py
└── abc/
├── __init__.py
└── A.py
My understanding is that if I want to use a function func_1()
from the functions
module, I would have to run any of the following:
import my_pckg.functions as pckg_fun
pckg_fun.func_1()
from my_pckg.functions import func_1
func_1()
Equally, if I want to import a function func_A()
from the A
module of the abc
subpackage, all I would have to do is use any of the following options:
import my_pckg.abc.A as pckg_A
pckg_A.func_A()
from my_pckg.abc.A import func_A
func_A()
Now, when I'm working with Python libraries like Numpy and I want to use the randn()
function from the random subpackage, for example, I can simply do
import numpy as np
np.random.randn(2)
Whereas if I run the following snippet
import my_pckg as mp
mp.functions.func_1()
or
import my_pckg as mp
mp.abc.A.func_A()
I get an error like this one:
>>> mp.functions.func_1()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: module 'my_pckg' has no attribute 'functions'
or this one, respectively
>>> mp.abc.A.func_A()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: module 'my_pckg' has no attribute 'abc'
So, I'm guessing that either there's more to creating modules that I thought, or I'm not understanding how modules like NumPy actually work.
Finally this joke by Mitch Hedberg truly summarizes the way I feel about all this:
They say the recipe for Sprite is lemon and lime, but I tried to make it at home, there's more to it than that. [...]
In __init__.py
add import statements of the stuff you want to use from that module when you import only the module.
Using your example, in my_pckg/__init__.py
, you would have
import functions
import abc.A
After that, you should be able to do what you described with no problems.
Edit: Best practices for import within packages are slightly different. Even with modules in the same folder, instead of directly importing, you should import from .
like this:
from . import functions
from abc import A
The side effect to the second line is that you will directly call mp.A.func_A()
instead of mp.abc.A.func_A()