DEV Community

Oliver Pham
Oliver Pham

Posted on

Publish a Python Project in 5 Steps

This week, I've published Silkie, my Python static site generator (SSG), to PyPI. It may seem daunting at first, but you can publish your own Python package by following these 5 steps.

Start

To avoid most painful misconfiguration, I organized my project to follow a standard directory structure:

silkie
├── LICENSE
├── README.md
├── pyproject.toml
├── requirements.txt
├── setup.cfg
├── silkie
│   ├── __init__.py
│   ├── __main__.py
│   ├── cli.py
│   ├── ...
├── tests
└── tox.ini
Enter fullscreen mode Exit fullscreen mode

You might want to use Cookiecutter to set up a template for your Python project if you are starting from scratch.

We'll be uploading our package to PyPI, so we should have an account created on PyPI. In addition, you can also create another account on TestPyPI to test your package first before an official publication.

Configure

Setuptools, a popular and extensible library for packaging Python projects, seems like a perfect choice for my project. Configuration steps for it includes writing two files: pyproject.toml and setup.cfg.

The pyproject.toml file simply declares the requirements for building our package:

[build-system]
requires = [
    "setuptools>=42",
    "wheel"
]
build-backend = "setuptools.build_meta"
Enter fullscreen mode Exit fullscreen mode

Based on your project architecture, setup.cfg can be configured accordingly. I think this tutorial does a better job explaining the details, so you should definitely check it out. As for Silkie, this is how I set it up:

[metadata]
name = silkie
version = 1.0.7
...
description = Static site generator with the smoothness of silk
long_description = file: README.md
long_description_content_type = text/markdown
url = https://github.com/oliver-pham/silkie
project_urls =
    Bug Tracker = https://github.com/oliver-pham/silkie/issues
classifiers =
    Programming Language :: Python :: 3
    License :: OSI Approved :: MIT License
    Operating System :: OS Independent

[options]
packages = silkie
python_requires = >=3.9
install_requires =
    click >= 8.0.0
    markdown >= 3.3.0
    yattag >= 1.14.0
    python-frontmatter >= 1.0.0

[options.entry_points]
console_scripts = 
    silkie = silkie.cli:silkie
Enter fullscreen mode Exit fullscreen mode

Some notes you may want to consider to avoid some misconfigurations (that I made):

  • packages: I specify silkie directory directly because my project only has a single package. If you have multiple packages nested under a single directory, you should use find: and follow the instructions in Setuptools documentation
  • install_requires: specify all third-party dependencies that your project use. Simply put, anything that you pip install and import in your code should be declared here

Build

Once you are done with configuration, let's build your Python package.

Before we can build it, make sure you have the latest version of build installed on your machine.

$ pip install --upgrade build
Enter fullscreen mode Exit fullscreen mode

Then, just run build in the root directory of your project:

$ python -m build
Enter fullscreen mode Exit fullscreen mode

You should have a .whl file and a .tar.gz file inside your dist/ directory when the build process is completed.

Test

Before publishing your package, make sure that the newly built distribution contains all the necessary packages and files. You can run this command to see what's inside your distribution:

$ tar tzf <your-package-name>.tar.gz
Enter fullscreen mode Exit fullscreen mode

Publish

To publish your Python package to PyPI, you must have twine installed on your machine. You can install its latest version with pip:

$ pip install --upgrade twine
Enter fullscreen mode Exit fullscreen mode

Once it's installed, run this command to upload your distribution to TestPyPI for testing:

$ twine upload --repository TestPyPI dist/*
Enter fullscreen mode Exit fullscreen mode

When prompted, you can either enter your account credentials or use an API token like this:

Enter your username: __token__
Enter your password: <your-API-token>
Enter fullscreen mode Exit fullscreen mode

When your package can be uploaded to TestPyPI and installed on your local machine, you're ready to upload it to PyPI:

$ twine upload dist/*
Enter fullscreen mode Exit fullscreen mode

Just like TestPyPI, your credentials or API token (for PyPI) can be used to authenticate your upload. Congratulations! You can now ask others to install and test your package.

As for Silkie, I've asked some of my friends to test the SSG. One of them found a critical bug due to a lack of testing. Another one suggested a piece of ASCII Art to me for Silkie, which was really nice. Overall, we have only tested it on Mac and Linux. If you happen to encounter any bug or issue while using Silkie, feel free to open an issue on GitHub.

Final thoughts

In general, I think publishing a Python package isn't really complex, but I was so nervous that I made a lot mistakes. It's fine if you mess up your release because you can always apply a new patch to it (unless your package is used by a majority of developers). Happy coding!

Discussion (0)