Publishing my open source project to PyPI!

katiel

Katie Liu

Posted on November 25, 2023

Publishing my open source project to PyPI!

This week I released my Python open source project go-go-web using PyPI! This means users no longer have to clone my repo in order to run my app. One simple pip install gogoweb command can install the app for anyone!

Here's the process for releasing Python software using PyPI.

If you prefer to watch a video, I recommend PyPi - How to Publish your own PIP package by DevOpsJourney. In addition, please see official Python documentation on packaging projects.

1) Create a PyPI account and create an API token

  • Register at PyPI.org
  • Generate recovery codes (mandatory step)
  • Activate Two Factor Authentication (mandatory step)
  • Generate API token (save the value!)

2) Install / upgrade package manager, build, publishing tools

Windows

py -m pip install --upgrade pip
py -m pip install --upgrade build
py -m pip install --upgrade twine
Enter fullscreen mode Exit fullscreen mode

Linux/MAC OS

python3 -m pip install --upgrade pip
python3 -m pip install --upgrade build
python3 -m pip install --upgrade twine
Enter fullscreen mode Exit fullscreen mode

3) Restructure your project to have the following structure

project_root/
├── LICENSE
├── pyproject.toml
├── README.md
├── setup.cfg
├── src/
│   └── package_name/
│       ├── __init__.py
│       └── programcode.py
└── tests/
Enter fullscreen mode Exit fullscreen mode

package_name/ : Name this directory the name you would like your software to have when users do pip install. For example, I used gogoweb, so users use pip install gogoweb. This name must not be already taken.

To check if a name is taken:

There must be an __init__.py file in the package_name folder.

All source files and referenced files for running your project should be inside the package_name directory.

This is my project structure:

project structure

4) Make sure your program still runs successfully on local after restructuring

I had to make changes to my source code in order for the package to run properly:

  • When importing modules from the current directory, changedimport module_name to from . import module_name
    • This was a fix I did later after releasing my package, because I found that the packaged file, when run, would try to import from the current working directory instead of where the packaged file is situated unless I employ this fix
  • Changed the logic in my code to output files by default to a til folder in the current working directory instead of the source code folder
    • This is for user convenience, because the installed package will be in an obscure location like C:\Users\katie\AppData\Local\Programs\Python\Python312\Lib\site-packages\gogoweb and users probably won't want to navigate there to get their output files
  • Updated the import statements in my unit test files and unit test config file since the paths of source files changed

  • Updated the pylint command in my CI Workflow .yml file since the directory containing the source files to be linted changed

5) Contents of pyproject.toml

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

[project]
name = "gogoweb"
authors = [
    {name = "Katie Liu", email = "liu_katie@outlook.com"}
]
readme = "README.md"
requires-python = ">=3.7"
classifiers = ["License :: OSI Approved :: MIT License"]
dynamic = ["version", "description"]

dependencies = [
    "tomlkit",
    "python-frontmatter"
]

[project.urls]
Homepage = "https://github.com/kliu57/go-go-web"
Issues = "https://github.com/kliu57/go-go-web/issues"
Enter fullscreen mode Exit fullscreen mode

Not everything I have in pyproject.toml is mandatory. The mandatory items are:

  • [build-system] section
  • [project] section - dependencies (Packages that need to be installed for your program to run successfully. I.e. my program requires the user to do pip install tomlkit and pip install python-frontmatter before running the program.)

6) Contents of setup.cfg

Replace with your own project values.

[metadata]
name = gogoweb
version = 1.0.3
author = Katie Liu
author_email = liu_katie@outlook.com
description = Command-line tool that converts .txt or .md files into .html files.
long_description = file: README.md
long_description_content_type = text/markdown
url = https://github.com/kliu57/go-go-web
project_urls =
    Bug Tracker = https://github.com/kliu57/go-go-web/issues
classifiers =
    Programming Language :: Python :: 3
    License :: OSI Approved :: MIT License
    Operating System :: OS Independent

[options]
package_dir =
    = src
packages = find:
python_requires = >=3.7

[options.packages.find]
where = src
Enter fullscreen mode Exit fullscreen mode

7) Create the build

Windows

py -m build
Enter fullscreen mode Exit fullscreen mode

Linux/MAC OS

python3 -m build
Enter fullscreen mode Exit fullscreen mode

After you run this command, you should get a "Successfully built" message with a file name that corresponds to the version number you specified in the setup.cfg. Check that the newly created dist/ directory contains that file. If not, troubleshoot before continuing further.

dist directory

8) Upload your package

Windows

py -m twine upload dist/*
Enter fullscreen mode Exit fullscreen mode

Linux/MAC OS

python3 -m twine upload dist/*
Enter fullscreen mode Exit fullscreen mode

You will be prompted to enter a username and password. For the username, enter __token__. For the password, copy and then paste your PyPI API token value from Step 1 (On a terminal you can right click to paste).

Successful upload to PyPI:

upload

Once uploaded, my project has its own PyPI website!

PyPI site

Now that the project is uploaded to PyPI, anyone can download it with a simple pip install command:

Windows

pip install gogoweb
Enter fullscreen mode Exit fullscreen mode

Linux/MAC OS

python3 -m pip install gogoweb
Enter fullscreen mode Exit fullscreen mode

I can check details of the installation and where the files were installed to:

Windows

pip show gogoweb
Enter fullscreen mode Exit fullscreen mode

Linux/MAC OS

python3 -m pip show gogoweb
Enter fullscreen mode Exit fullscreen mode

pip show

After installing, my command-line app can be run with this command.

Windows

py -m gogoweb.convert <file or folder path>
Enter fullscreen mode Exit fullscreen mode

Linux/MAC OS

python3 -m gogoweb.convert <file or folder path>
Enter fullscreen mode Exit fullscreen mode

This will take the file or folder and convert any .txt and .md files into .html files. Default output location is a til folder in the current working directory. See go-go-web documentation for more details.

powershell run

input and output


Run your package and more

Notice that gogoweb the name of my package and convert is the name of the .py file I want to run. For your package, if you wanted to run a python file from that package:

Windows

py -m <your package>.<your file> [args]
Enter fullscreen mode Exit fullscreen mode

Linux/MAC OS

python3 -m gogoweb.convert <your package>.<your file> [args]
Enter fullscreen mode Exit fullscreen mode

There are many things you could do with your package once installed. For example you could call certain functions that are inside your package:

from <package_name> import <file_name> as pf

pf.somefunction()
Enter fullscreen mode Exit fullscreen mode

Reuploading a package

  • Increment the version number in setup.cfg
  • Repeat step 7 to recreate the build
  • Repeat step 8 to upload the build

User Testing

Roy and Amnish were kind enough to test my app installation and run! Amnish had no issues with the app, and Roy helped me find and find a fix for a unique issue arising from multiple version of Python installed on his machine. The pip install installed the app to his Python v3.11 directory, while his terminal python run command is looking for the app in the Python v3.12 directory.

Error

The fix for this is to first find out what Python directory the app was installed to with pip show gogoweb

pip show

Then we specify a Python version with our run command:

py -<version number> -m gogoweb.convert [args]
Enter fullscreen mode Exit fullscreen mode

specifying python version run


I am very happy to have completed my first software release. Users can now read instructions to install my program with pip on my repo!

💖 💪 🙅 🚩
katiel
Katie Liu

Posted on November 25, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related