You built an amazing tool, organized your Python functions, and now you want the whole world to install it with a simple pip install command. Publishing to PyPI (Python Package Index) is the rite of passage for any developer who wants to contribute to the community. While it may seem bureaucratic, it is perfectly possible to configure everything and upload in under 5 minutes. This guide gives you a practical step-by-step to turn your scripts into professional, globally accessible Python libraries.
What is PyPI and why should you publish there?
PyPI is the official software repository for the Python language. Think of it as a massive digital library where any programmer can “borrow” ready-to-use code for their own projects. When you publish a package, you make other developers’ lives easier and improve your portfolio. PyPI also manages dependencies automatically: if your project needs other tools, the Python installer handles everything for the end user, avoiding manual errors and ensuring your software works across different environments.
Prerequisites for publishing your Python package
Before starting the 5-minute clock, you need three things ready. First, an account on PyPI. Second, an account on TestPyPI, which is an identical test server used to verify nothing goes wrong before the real publication. Third, make sure your code follows good practices, which makes your library far more professional. You also need pip updated and the build tools installed:
python -m pip install --upgrade build twineProject folder structure
For PyPI to understand what should be packaged, your project needs a specific structure. Assuming your package name is my_magic_package, the organization must look like this:
my_project/
├── my_magic_package/
│ ├── __init__.py
│ └── core.py
├── tests/
├── README.md
├── LICENSE
├── pyproject.toml
└── setup.cfgThe __init__.py file can be empty, but it tells Python that the folder is a package. The README.md explains what the project does, and the LICENSE defines how people can use your code (such as the MIT license).
Step 1: Create the pyproject.toml configuration file
The pyproject.toml file is the heart of your packaging. It replaced the old setup.py in modern Python. Here is a minimal example you can copy:
[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"Step 2: Generate the distribution files (build)
With the structure ready, open the terminal in the root folder of your project (where pyproject.toml is). Run the following command to generate the files that will be sent to the server:
python -m buildThis creates a dist/ folder containing a .tar.gz (source code) and a .whl (built distribution). These are the compressed files pip downloads when someone requests your library. To manage Python dependencies more robustly, consider using Poetry to handle versioning and publishing in a single workflow.
Step 3: Create an API token for security
PyPI now requires API tokens instead of username/password authentication. Go to your PyPI account settings, click “Add API Token”, give it a name, and select the scope (initially “Entire account”). Copy the token immediately after it is generated — it starts with pypi- and you will not be able to see it again. This token replaces your password. The username for terminal uploads is always __token__.
Step 4: Upload to TestPyPI first
Before publishing to the world, send to the test server. This verifies your pyproject.toml is correct and the package can be installed without errors:
python -m twine upload --repository testpypi dist/*
# Then test installation:
pip install -i https://test.pypi.org/simple/ my-magic-packageStep 5: Publish to official PyPI
If the test worked, run the upload command without specifying the test repository. Twine will target the official server directly:
python -m twine upload dist/*Enter __token__ as the username and paste your official PyPI API token as the password. Your package is now available to millions of developers worldwide. See the official Python distribution documentation for advanced configuration options.
Managing versions: how to update your package
To update your package, follow three simple steps: open pyproject.toml and increment the version (e.g. from 0.0.1 to 0.0.2), delete the old dist/ and build/ folders, then run python -m build and python -m twine upload dist/* again. PyPI does not allow uploading different files with the same version number, which guarantees the integrity of projects that depend on your library.
Example package code structure
# File: my_magic_package/core.py
def magic_greeting(name):
"""A simple function to test the package."""
return f "Hello {name}, this package was installed via PyPI!"In your __init__.py, expose the functions for easy access: from .core import magic_greeting, add_numbers. To automate publishing on every push, connect this workflow with GitHub Actions for Python CI/CD.
Frequently asked questions
Can I publish a package with the same name as an existing one?
No. PyPI requires unique names. If you try to publish a project called “requests” or “pandas”, the upload will be rejected immediately.
Is TestPyPI required before the official one?
Not required, but highly recommended. It prevents you from publishing versions with README formatting errors or incorrect metadata, which would waste version numbers.
How do I remove a package I published by mistake?
You can remove specific versions or the entire project through the dashboard on the PyPI website. However, removing versions others may already be using is discouraged.
What are classifiers in pyproject.toml?
They are tags that help people find your project. They indicate whether the code is for Python 3, what the license is, and which operating systems it runs on.
Is there a cost to publish on PyPI?
No, the service is completely free and maintained by the Python Software Foundation through donations and sponsorships.
The twine command was not recognized. What should I do?
This happens when Python’s scripts directory is not in the PATH. Use python -m twine instead of just twine.
How do I add external dependencies to my package?
Inside pyproject.toml, in the [project] section, add a list: dependencies = ["requests", "numpy"].
Publishing your first package is just the beginning of your journey as an open source contributor. Over time, you can automate this process with tools like GitHub Actions, where every push to your repository automatically results in a new PyPI release.






