September 12, 2022 python imports pain
Any budding python program has been there. You’ve just made a wonderful new project with an amazingly descriptive file structure! Well done you!
foo ├── bar │ ├── bar.py │ └── __init__.py └── __init__.py
foo/__init__.py is empty making foo a module, and since
foo/bar also has a
__init__.py file, it is a submodule. For the purposes of this little demonstration, the files are as follows:
# foo/bar/__init__.py from .bar import bar # foo/bar/bar.py """ This is a really important module! """ def bar(): print("Hello, World!")
Everything works real nicely except you find yourself needing to call
help() on the
bar sub-submodule (i.e.
foo.bar.bar.bar). How do we do this?
>>> from foo.bar import bar >>> help(bar) Help on function bar in module foo.bar.bar: bar()
Well, that was expected right? Let’s try something different…
>>> import foo.bar.bar >>> help(foo.bar.bar) Help on function bar in module foo.bar.bar: bar()
Shoot! Same again.
>>> import foo.bar as b >>> help(b.bar) Help on function baz in module foo.bar.bar: baz()
You see what’s going on here?
Because we’ve named our function the same as the submodule(yes,
bar.py is being treated as a submodule within the submodule
bar), and we’re OVERWRITING the submodule’s name in
foo/bar/__init__.py, it’s impossible to access anything within the submodule other than
bar(). However, with an empty init file, we could have called help on the submodule as:
>>> from foo.bar import bar >>> help(bar) Help on module foo.bar.bar in foo.bar: NAME foo.bar.bar - This is a really import module! FUNCTIONS bar() FILE foo/bar/bar.py
__init__.pyfile if possible
bar, then name the file
_bar.pyand the function something a little more creative such as
And another top tip, make good use of the