Creating a Python package
Creating a Python package and uploading it to PyPI or Test PyPI isn’t that complicated, but there are a few details I want to remember next time. Some of the steps below reflect my personal preferences and are not necessary.
Creating a basic package
To create a package, do the following:
- Create a directory called
packagename
that has a structure akin to the below:
|
|
Add project descriptions to
README.md
Add the appropriate text to
LICENSE
Add the following contents to
pyproject.toml
:
|
|
Create a virtual environment:
python3.10 -m venv .venv
Activate the virtual environment:
source ./.venv/bin/activate
Initialise Git and create a GitHub repo as usual (only the files in
projectname\dist
get uploaded, so there is nothing special about the rest of the directory)Write some code to put in the package …
Install distribution and upload dependencies:
|
|
Build the package:
python3 -m build
Upload the build files to…
- Test PyPI:
python3 -m twine upload --repository testpypi dist/*
- PyPI:
python3 -m twine upload dist/*
- Test PyPI:
Done! You can now install your package using
python -m pip install packagename
(from PyPI)python -m pip install --index-url https://test.pypi.org/simple/ --no-deps packagename
(from Test PyPI)
Organising your package
I often want to organise the modules in my package into subpackages and submodules for additional structure. Something like the below:
|
|
and, if the content of a.py
is:
|
|
I want to be able to import my package as import packagename as p
, and then access function a
in module a
as p.subpackage1.a
.
To be able to do that, the __init.py__
in packagename
needs to contain:
|
|
so that module a
gets loaded into the namespace when I import the package, and __init.py__
in subpackage1
needs to contain
|
|
so that function a
gets loaded into the namespace when I import module a
.
Creating tokens for pypi and test pypi
When uploading packages to either Test PyPI or PyPI, the default behaviour of Twine is to ask for the username and passwort on the respective platform. A more secure and much easier way to verify your identity is to create a tocken in your user account, and save the details in your ~/.pypirc
file. Twine then automatically sources those details during the upload process.
Your ~/.pypirc
would look something like this:
|
|
Versioning
Making new versions of a package is so easy nobody even seems to bother to mention how it’s done. So here are the steps:
Make the desired changes in the code
Change the
version
field inpyproject.toml
Rebuild the package (see above for command)
Upload build files (see above for command)
Useful tools
There are a lot of packaging tools that automate some of the above. I’ve tried Poetry in the past, and Hatch this time. But I find that all these tools do many things I neither need nor understand. So, for the time being, I’ll keep things simple and just follow the process above.