This is an old revision of the document!
Table of Contents
Packaging
In Python, individual source files are referred to as modules. They represent a single collection of code, and can be import
ed. Packages are directories containing an __init__.py
file and other modules. They are comparable to namespaces, and can also be import
ed. A package with an empty __init__.py
file is completely fine; it just won't import any modules when imported.
Here's an example of a package containing modules:
my_package/ __init__.py ui.py attribute.py model.py router.py
There are multiple ways to interact with a package, which are covered below. In every case, it's assumed that the Python interpreter is in the directory above my_package/
, or my_package/
is somewhere in Python's path variable. See Python's documentation on sys.path for information on that.
Simple Importing
# Import just the package import my_package
In this case, importing the package will process everything that's in __init__.py
, including any pre-defined import
s. It's considered good practice to define which modules get imported by default when importing a package, to ensure only the necessary modules are loaded. Your modules can individually import
any part of the package they need to get the job done. To do this, your __init__.py
should look somewhat like this:
- __init__.py
# Let's say you only need the model and router to get started from . import (model, router)
The .
here means "the current package". If you have sub-packages, you can address them with a dot preceding its name, like .my_subpackage
.
Single Module Importing
Sometimes, you only need a single module from a package. That's easy:
# Import only the UI from my_package import ui
In this example, only the ui
module is imported. It gets injected into the current environment as ui
, and you can access its members as well, using something like ui.create_box()
.
Single Member Importing
Lastly, sometimes you need only specific parts of a module. That's easy, too!
# Import only specific things from a given module from my_package.router import do_route
In the above example, do_route
will become available in the current environment, imported from the router
module inside the my_package
package.
If you find yourself with strange NameError
s, AttributeError
s, or ValueError
s, it may point to a name collision. You can rename your imports with the as
keyword:
# Import with a different name from my_package.router import do_route as make_route
This is often caused by importing two modules with the same member name. If you import two things with the same member name, the latter name will take precedence:
# Same name, different structures from os import path print(type(path)) # <class 'module'> from sys import path print(type(path)) # <class 'list'>
For this reason, it's generally better to leave imports alone and go one level deeper only as needed. So if you wanted to use path
from both os
and sys
, just import them on their own, so you're using os.path
and sys.path
. It's more verbose, but also more precise and less likely to break.