I know about packages that differentiate between imported implicit components (via import thepackage
) and explicit imported components (via 'import thepackage.explicte_component`).
I want to have this for my own package and wonder how this could be implemented in the folder and file structure of my package in a pythonic way. I can produce the expected behavior in my example here. But the question is if this is a good solution or if there is a better pythonic way for this.
Here is another real world example where matplotlib.pyplot
is not usable until it is explicit imported.
Python 3.9.10 (tags/v3.9.10:f2f3f53, Jan 17 2022, 15:14:21) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import matplotlib
>>> matplotlib.pyplot
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Users\buhtzch\AppData\Roaming\Python\Python39\site-packages\matplotlib\_api\__init__.py", line 222, in __getattr__
raise AttributeError(
AttributeError: module 'matplotlib' has no attribute 'pyplot'
>>> import matplotlib.pyplot
>>> matplotlib.pyplot
<module 'matplotlib.pyplot' from 'C:\\Users\\buhtzch\\AppData\\Roaming\\Python\\Python39\\site-packages\\matplotlib\\pyplot.py'>
My own example currently looks like this
mypackage_prj
├── LICENSE
├── README.md
├── src
│ ├── mypackage
│ │ ├── a.py
│ │ ├── __init__.py
│ │ └── _mypackage.py
│ ├── setup.cfg
│ └── setup.py
└── tests
└── ...
The simple src/mypackage/__init__.py
only does from ._mypackage import *
. The src/mypackage/_mypackage.py
defines foo()
. So I can do
import mypackage
mypackage.foo()
The submodule src/mypackage/a.py
defines a bar()
. This would throw an exeption because a
is not imported yet.
import mypackage
mypackage.a.bar()
But this would work
import mypackage
import mypackage.a
mypackage.a.bar()
My current solution with the _mypackage.py
file works for my self. But I have some side effects in my environment because of that "private" (?) py-file. For example Sphinx has problems with filenames beginning with an underscore. It does not matter here that the Sphinx problem can be solved by an extra commandline switch. The point is that I assume that my solution is not good or standard because Sphinx can not handle it by default.
I want to overcome this workarounds and wondered if there is a better more pythonic standard way to do things like this.