The Modern Way of Uploading a PyPi Package
Tags: python, packaging, tutorial, pypi
Published: 2022-09-22 15:00:32

There are a lot of conflicting guides when it comes to uploading your first package onto PyPi. This guide will show you the modern way to upload your python package onto PyPi as well as some common pitfalls to avoid.

## Before You Begin
Make sure you have `setuptools` and the command line tool `build` installed in the virtual environment you have created your package's code in. To install build run `pip install --upgrade build`. You will also need to install `twine` in order to upload the package to pypi. Use the command `pip install twine` to install twine in your virtual environment.

```
pip install setuptools twine
pip install --upgrade build
```

## 1. Build your wheel and dist
**Command:** `python -m build`

This creates the `wheel` and `dist`(short for source distribution) for your project. It the recommended way to build your python package ever since [`setup.py` was deprecated](https://setuptools.pypa.io/en/latest/deprecated/commands.html). This command works just like the deprecated `python setup.py sdist/*` way of creating a source distribution. It works great with a `pyproject.toml` to build you sdist and wheel.

If you run `python -m build` with the same version number  in your `pyproject.toml` or `setup.cfg` it will replace that version of `wheel` and `sdist`. For example if you already ran `python -m build` when your `pyproject.toml` had `version = 0.0.03` and then modified your code you could run `python -m build` to replace the `version = 0.0.03` of sdist and wheel you built previously. This will only work if you haven't already uploaded that version number to PyPi.



## 2. Check your package's before upload
**Command:** `twine check dist/*`
**Check specific version:** `twine check dist/*0.0.1*`

`twine check` checks your long description (or readme) to see if it will render correctly on PyPi.

⚠️**WARNING**⚠️
If you use the dynamic readme option in your `pyproject.toml` and your README file is not named exactly `README` the `twine check` will fail and return the error message. However the package can still up successfully uploaded to PyPi even when the check fails. It just means the readme might not render correctly on PyPi.

## 3. Upload to Test PyPi (Optional)
**Command:**`twine upload --repository testpypi dist`

Pypi has a test version where you can upload packages without impacting the real PyPi index. This is a great place to get familiar with uploading to PyPi without the stress of impacting the PyPi index.

⚠️**WARNING!**⚠️
Don't upload any packages with dependencies to Test Pypi because the dependencies are not guaranteed to be uploaded on Test Pypi. This may cause your installations from Test PyPi may randomly fail because pip will try to find your dependencies on Test PyPi where they don't exist.

## 4. Upload to PyPi with Twine
🚀**Command:**`twine upload dist/*`

This command uses a pip package called [Twine](#what-is-twine) to upload your package to PyPi.

When you run this command you will be prompted to enter your password unless you have configured a tool like [keyring](https://pypi.org/project/keyring/) to automatically enter your credentials.

### Configure KeyRing to Automatically Enter PyPi Credentials
1. Install keyring in your virtual environment `pip install keyring`
2. Save your username and password with keyring. In your virtual environment's command prompt enter: 
 - Make sure to put a space between the link and YOUR_USERNAME
```
keyring set https://upload.pypi.org/legacy/ <YOUR USERNAME>
Enter your password when prompted
```
Example
```
keyring set https://upload.pypi.org/legacy/ ms_username
<click enter>
my_fake_password
```

- If you're a Windows user and don't see your password being entered in the window don't worry that's normal!

### Want to upload a specific version of your package?
**Command:** `twine upload dist/*<version_number>*`
- If you want to upload a specific version of your package here is a shortcut
- **Example:** `twine upload dist/*0.0.6*`
- This will upload all the dist files (wheel and tar) with version number = 0.0.6.

### What is Twine?
- Twine is a super easy to use package that lets you upload to PyPi or Test PyPi with a single command.
- You can install it with pip using the command `pip install twine`