From Code to PyPI: A Complete Guide to Publishing Your Python Package
You’ve built a Python script, a handy library, or a cool command-line tool. It works perfectly on your machine. Now what? The next step is…
From Code to PyPI: A Complete Guide to Publishing Your Python Package
You’ve built a Python script, a handy library, or a cool command-line tool. It works perfectly on your machine. Now what? The next step is to share it with the world by publishing it to the Python Package Index (PyPI), making it installable with a simple pip install.
This guide will walk you through the entire modern process, I have done this while creating my learning project named json-parser-cli on PyPI. github link for json-parser
1. The Pre-Flight Checklist: Is Your Project Ready?
Before you can even think about uploading, your project needs to be structured correctly. A clean setup prevents major headaches later.
The Blueprint: pyproject.toml
This is the most important file in a modern Python project. It’s the central configuration file that tells packaging tools everything they need to know. Here’s a minimal but complete example:
[project]
name = "your-package-name"
version = "0.1.0"
description = "A brief description of your package."
readme = "README.md"
requires-python = ">=3.8"
license = {text = "MIT"}
authors = [
{name = "Your Name", email = "your@email.com"}
]
keywords = ["cli", "data-science", "api"]
# This section creates the command-line tool (optional)
[project.scripts]
your-command = "your_package.module:main_function"
# This tells the builder where to find your code
[tool.hatch.build.targets.wheel]
packages = ["src/your_package"]
**[project]**: Contains all your project's metadata. PyPI uses this to display information on your project page.**[project.scripts]**: This is magic. It tellspipto create a command-line script (e.g.,your-command) that calls a specific function in your code.**[tool.hatch.build.targets.wheel]**: This tells your build tool (in this case,hatchling) that your actual importable code lives inside thesrc/your_packagedirectory.
Essential Documentation: README.md & LICENSE.md
**README.md**: This is your project’s front page. It’s rendered directly on PyPI. A good README should clearly explain what your project does and how to use it.**LICENSE.md: This is non-negotiable. Without a license, your code is legally unusable by others. The MIT License** is a popular and simple choice for open-source projects. Make sure this file is not empty!
2. The Build Process: Creating Your Package
With your project configured, it’s time to build the distributable files.
Install the Tools
You need two packages for this: build and twine.
# Using pip
pip install build twine
# Or using uv
uv pip install build twine
Run the Build
From the root directory of your project, run:
python3 -m build
This command reads your pyproject.toml and uses the specified build backend to create a dist/ folder. Inside, you'll find two important files:
- A
**.whl(Wheel) file**: A pre-built package that’s fast to install. - A
**.tar.gz(Source Archive)**: Your raw source code, which can be built by the end-user.
3. The Launch: Uploading to PyPI
This is the final step to get your package live.
Create a PyPI Account and API Token
First, register an account on PyPI.org.
For security, do not use your password to upload. Instead, create an API token:
- Go to your Account Settings on PyPI.
- Scroll to API tokens and click “Add API token”.
- Give it a name and set its scope to “Entire account”.
- Copy the token(it starts with
pypi-). Save it somewhere safe; you will not see it again.
Run the Upload Command
Now, use twine to upload the files from your dist/ folder.
python3 -m twine upload dist/*
Twine will prompt you for your credentials.
- Username:
__token__ - Password: Paste your API token (the one starting with
pypi-).
Once the upload completes, your package is live! You can view it at [https://pypi.org/project/your-package-name/.](https://pypi.org/project/your-package-name/.)
4. Curing the Challenges: When Things Go Wrong
The steps above describe the perfect scenario. In reality, you’ll hit errors. Here are the most common ones and how to fix them.
Challenge 1: HTTPError: 403 Forbidden - The Versioning Mistake
You try to upload and see a 403 Forbidden or 400 Bad Request error saying "File already exists."
- Cause: You cannot upload the same version number twice. If version
0.1.0is already on PyPI, you can't upload it again, even if you've made changes. - Cure: Bump the version number in your
pyproject.tomlfile. Follow semantic versioning (MAJOR.MINOR.PATCH): 0.1.1: For a small bug fix or documentation update.0.2.0: For a new feature that is backward-compatible.1.0.0: For your first stable release or major breaking changes. After bumping the version, delete thedist/folder and re-run thebuildanduploadcommands.
Challenge 2: The Package Installs, but the Command Fails
You successfully publish your package, a friend installs it, but when they run your command, they get a ModuleNotFoundError.
- Cause: The build tool didn’t include all the necessary files. This often happens if your code is not properly structured. The modern standard is the
**srclayout**, where all your importable code lives in a subdirectory (e.g.,src/your_package/). - Cure: Make sure your
pyproject.tomlcorrectly points to your source directory, like in our example:packages = ["src/your_package"]. This ensures that only the code meant to be distributed is included, and nothing else.
Challenge 3: HTTPError: 404 Not Found (For GitHub Packages)
This is a bonus for those publishing to GitHub Packages. A 404 error there is almost always a permissions issue.
- Cause: The Personal Access Token (PAT) you are using is either a “fine-grained” token or a “classic” token that is missing the
**write:packages** scope. - Cure: Go to your GitHub Developer Settings and generate a new classic token, making sure the
write:packagespermission is explicitly checked.
Conclusion
Publishing your first Python package can seem daunting, but it boils down to a repeatable cycle: configure, build, and upload. By using modern tools like pyproject.toml, build, and twine, you're following the best practices of the Python community.
A message from our Founder
Hey, Sunil here. I wanted to take a moment to thank you for reading until the end and for being a part of this community.
Did you know that our team run these publications as a volunteer effort to over 200k supporters? We do not get paid by Medium!
If you want to show some love, please take a moment to follow me on LinkedIn, TikTok and Instagram. And before you go, don’t forget to clap and follow the writer️!
메타데이터
- post_id
- 9f00ee04dd3f
- slug
- from-code-to-pypi-a-complete-guide-to-publishing-your-python-package-9f00ee04dd3f
- url
- https://python.plainenglish.io/from-code-to-pypi-a-complete-guide-to-publishing-your-python-package-9f00ee04dd3f
- canonical_url
- https://python.plainenglish.io/from-code-to-pypi-a-complete-guide-to-publishing-your-python-package-9f00ee04dd3f
- author_url
- https://medium.com/@anandvashishtha
- status
- ok
- fetched_at
- 2026-07-18 16:25:27