
If you've ever built something in Python and want to share it with others, you'll probably want to bundle it into a package.
A package in Python is a directory that groups related Python modules together so the directory can be imported as a single Python namespace. To simply put, it makes your code reusable and shareable.
Instead of having users clone down your repository from GitHub, you’ll bundle it all together into a package, deploy it onto pypi, and have developers install it using a package manager such as pip and uv.
Python packaging basics:
A package can contain multiple Python files, and each file is a module. Together, they’re organized under one folder (the package), with an __init__.py to tie it all together and a pyproject.toml file that describes it.
Creating and Naming a Package:
Start by creating a new directory and putting your Python scripts in it. While naming your package, keep these things in mind:
The name of the package should reflect its functionality and be unique if publishing to PyPI.
Keep the name lowercase, short, and descriptive.
It’s okay to use hyphens in the distribution name. Distribution name is the name we use to install it as a package, like:
pip install pandas
Package directory name should have a valid identifier. It’s used to import the package, has to follow the same rules as a Python identifier.
Creating an __init__.py file:
It’s an entry point to your package - tells Python that this package is importable.
Note: It was mandatory to have an __init__.py file in the package pre Python (3.3), but thanks to “namespace packages”, it’s not necessary. It’s generally considered a good practice to have one, though.
The first thing that executes when you import a module is the __init__.py which enables you to set defaults, import submodules, and store package metadata.
# __init__.py
__version__ = "0.1.0"
# re-export a function from inference.py
from .inference import predict_disruptions
__all__ = ["predict_disruptions", "__version__"]
Let’s break it down:
__version__: It serves as runtime metadata, useful for debugging, logging, and version tracking.
Import Statement: Why did we put an import in the __init__.py file? The reason is that it makes importing from the package easier.
# Before re-exporting function in init.py
from logistics_forecaster.inference import predict_disruptions
# After adding the import statement in init.py
from logisitic_forecaster import predict_disruptions
_all_: Only the names listed in this list are allowed to be imported. Python wouldn’t let you import anything else otherwise.
Making pyproject.toml file:
pyproject.toml is configuration file that describes your Python package. TOML format is just like YAML or JSON but less prone to errors and much easier to read.
Note: Version in pyproject.toml file is used by PyPI and other build tools when packaging and publishing your project.
[project]
name = "logistics-forecaster"
version = "0.1.0"
description = "Predict logistics risks using weather data."
authors = [{ name = "Brandon" }]
dependencies = ["requests>=2.32"]
[project.scripts]
logistics-forecaster = "logistics_forecaster.cli:main"
Installing the package also creates a command called logistics-forecaster via the project.scripts entry in pyproject.toml.
The final project structure should look something like this:
logistics-forecaster/
├─ logistics_forecaster/
│ ├─ __init__.py
│ └─ inference.py
├─ pyproject.toml
└─ README.md
Building the package:
Next step is building the package you just created by running the following commands:
# Navigate into your project
cd logistics-forecaster
# Install the build tool that creates installable packages (artifacts)
python -m pip install -U pip build
# Install your package in your development environment
pip install -e .
# Run a quick sanity test
python -c "import logistics_forecaster as lf; print(lf.predict_disruptions(24))"
Deploying your Package to PYPI:
After creating your package you can deploy it to PyPI. You’ll need a valid PyPI account and an API token. First, build your distribution; this will create files in the dist/ folder:
python -m pip install build
python -m build
You can upload those file to PyPI by running this command:
twine upload dist/*
And, voila! You are done.
Happy coding!
📧 Join the Python Snacks Newsletter! 🐍
Want even more Python-related content that’s useful? Here’s 3 reasons why you should subscribe the Python Snacks newsletter:
Get Ahead in Python with bite-sized Python tips and tricks delivered straight to your inbox, like the one above.
Exclusive Subscriber Perks: Receive a curated selection of up to 6 high-impact Python resources, tips, and exclusive insights with each email.
Get Smarter with Python in under 5 minutes. Your next Python breakthrough could just an email away.
You can unsubscribe at any time.
Interested in starting a newsletter or a blog?
Do you have a wealth of knowledge and insights to share with the world? Starting your own newsletter or blog is an excellent way to establish yourself as an authority in your field, connect with a like-minded community, and open up new opportunities.
If TikTok, Twitter, Facebook, or other social media platforms were to get banned, you’d lose all your followers. This is why you should start a newsletter: you own your audience.
This article may contain affiliate links. Affiliate links come at no cost to you and support the costs of this blog. Should you purchase a product/service from an affiliate link, it will come at no additional cost to you.