timerring

How to Publish Your Code as a Pip Module

January 7, 2025 · 2 min read · Page View:
Tutorial
Python | pip | module

A simple manual for publishing your code as a pip module.

If you have any questions, feel free to comment below.

Last week, I have made a python cli tool. To make it more convenient to use, I want to publish it as a pip module, so I have made some research and mistakes, and finally succeeded.

Prerequisites #

  1. Register a pypi account in the official website
  2. Apply a token in the pypi management page
  3. Make sure your module name will be unique, you can check it in the pypi search page

Check your code #

  1. Make sure your code is in a “package” folder (Must have __init__.py file)
  2. Create a README.md
  3. Create a LICENSE
  4. Create the pyproject.toml file in the root folder of the package, you can use the following content as a template:
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "biliupload" # make sure your module name is unique
version = "0.0.1"
authors = [
  { name="timerring"},
]
description = "Login and upload videos to bilibili"
readme = "README.md"
license = { file="LICENSE" }
requires-python = ">=3.10"
classifiers = [
    "Programming Language :: Python :: 3",
    "License :: OSI Approved :: MIT License",
    "Operating System :: OS Independent",
]
dependencies = [
  "PyYAML==6.0.2",
  "qrcode==8.0",
  "Requests==2.32.3",
  "requests_html==0.10.0",
]

[project.urls]
"Homepage" = "https://github.com/timerring/biliupload"

The below is the basic template, if you are making a cli tool, you also need to add the project.scripts section.

For more details, you can refer to the official documentation

Build the package #

  1. Latest version of PyPA’s build is recommended
python3 -m pip install --upgrade build
  1. Build the package(run this command from the same directory where pyproject.toml is located)
python3 -m build

You will see the following output in dist/ folder:

  • .whl file: the built distribution
  • .tar.gz file: the source distribution

Upload distribution archive for TestPyPI #

The TestPyPI is a isolated website of PyPI, you can upload your package to it first to check if it works.

  1. Register on TestPyPI
  2. Apply a token in the TestPyPI management page
  3. install the twine package python3 -m pip install --upgrade twine
  4. upload the distribution packages via python3 -m twine upload --repository testpypi dist/* and you can check your package.
  5. Test your package in a new environment python3 -m pip install --index-url https://test.pypi.org/simple/ biliupload

That maybe have some problems, you can refer to the Conflict problem section to fix it.

Upload distribution archive formally #

  1. Make sure your production version for build is ready
  2. Upload the distribution archive via python3 -m twine upload dist/*
  3. Then you can pip it formally pip install biliupload

Your can also refer to the official documentation if you want more details.

Additionally, you may also want to make it into a executable file, you can just use the pyinstaller package command pyinstaller -F biliupload/cli.py to do it.

Note: pyinstaller is not a cross-platform compiler, you need to compile it on the platform you want to run it on via docker or some other tools. And if you want to Using Data Files from a Module, don’t forget to include it via pyinstaller --add-data "bilitool/authenticate/config.json:bilitool/authenticate" -F bilitool/cli.py.

Conflict problem #

You may encounter the following error:

The conflict is caused by:
    biliupload 0.1.1 depends on pyyaml==6.0.2
    biliupload 0.1.0 depends on pyyaml==6.0.2

To fix this you could try to:
1. loosen the range of package versions you've specified
2. remove package versions to allow pip to attempt to solve the dependency conflict

That is because you are using the pyyaml package which is not exist in the testpypi, so you can refer to this stackoverflow to fix it via pip install -i https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple biliupload==0.1.0, which the --extra-index-url pointer to the pypi.org.

Related readings


<< prev | Some Good... Continue strolling The Overview of... | next >>

If you find this blog useful and want to support my blog, need my skill for something, or have a coffee chat with me, feel free to: