Skip to content

Python packaging with Flit#

This post provides a simple starter demonstration on how to use Flit for building and publishing Python package. However, for more complex builds, such as compiling C code, you still need the de facto standard setuptools.


file pyproject.toml:

The flit-core github repo has already a good demo of pyproject.toml, and I just need to change a few lines:

requires = ["flit-core >= 3.9,<4"]
build-backend = "flit_core.buildapi"

# project name will be converted to kebab-case automatically
# when publishing to pypi.
name = "package_name_shown_in_pypi"
dynamic = ["version", "description"]
authors = [
    { name = "my name", email = "my email" },
requires-python = ">=3.11"
readme = ""
classifiers = [
    "Programming Language :: Python :: 3",
    "Topic :: Software Development :: Libraries :: Python Modules",
urls.repository = "repo url"
urls.documentation = "repo url"

dependencies = ["aiohttp"]

dev = ["pre-commit"]
doc = ["mkdocs"]

name = "python_module_folder_name"  # name used by import in Python

# non-Python data file are not included by flit by default, so add VERSION file here.
include = ["VERSION"]

Flit reads the variable __version__ from the module file python_module_folder_name/ to get the version number. The above example uses a file VERSION to store the version number, and the file reads the version number from the VERSION file. As a flat VERSION is more convenient to edit, I prefer this way.

So the python_module_folder_name/ file could look like:

"""An amazing sample package!"""
from pathlib import Path


    version_file_path = Path(__file__).resolve().parents[1] / "VERSION"
    __version__ = version_file_path.read_text().strip()
except FileNotFoundError:
    __version__ = DEFAULT_VERSION


After that, you can use build to build the package, and twine to upload the package to pypi:

pip install build
python -m build
twine upload -r [feed_name_configured_in_pypirc] dist/*.whl

I don't use flit build because I find python -m build to be more standard from my personal perspective, and I prefer using twine over flit publish for the same reason. For example, Azure Pipeline configures ~/.pypirc for twine with the built-in task TwineAuthenticate, but not for flit.