How to create a PyPi (Python) package
Tags: python
Published: 2022-01-06 21:04:03

Have you ever wanted to create a Python package so you can type the following?

```bash
pip install my-awesome-package
```

If so, this tutorial is for you. 

## 1. Getting Poetry
[Poetry](https://python-poetry.org/) is a system package you can use to **very easily** manage your Python Packages. 

It makes handling your packages super easy. I have 9 Python packages under my name, and this is by far the best solution. 

First, you need to install Poetry on your system. 

### osx / linux / bashonwindows install instructions
```bash
curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python -
```

### windows powershell install instructions
```bash
(Invoke-WebRequest -Uri https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py -UseBasicParsing).Content | python -
```

[More details about installation here](https://python-poetry.org/docs/#installation)

Now you can type `poetry --version` to see the version you're running. If this doesn't work for you, try closing and re-opening your terminal.

## 2. Creating a Poetry project 
In this tutorial we're going to create a new package from scratch. 

Go ahead and type:
```bash
poetry new test-package
```

As the docs mention, it'll create a new folder with a bunch of files for you that are structured like this:

```
test-package
├── pyproject.toml
├── README.rst
├── test_package
│   └── __init__.py
└── tests
    ├── __init__.py
    └── test_test_package.py
```

## 3. Adding your code
Create a new file in `test-package/test_package/` called `myfile.py`.

Your file structure should look like this now:
```
test-package
├── pyproject.toml
├── README.rst
├── test_package
│   ├── __init__.py
│   └── myfile.py  # <- This is new
└── tests
    ├── __init__.py
    └── test_test_package.py
```

All of your code will go in the `test_package/` folder. 

> Note: This folder name will be different if you used a different package name during step 2.

You can add any files you want in this folder. This is what get's bundled in your package.

Now in your `myfile.py` file, add this function:
```python
def custom_function(name):
    print(f"Hello {name}!")
```

Later we can use this code like so: 
```python
from test_package.myfile import custom_function
```

👆 We'll get to that later, first we need to build the package. 

## 4. Building your package
So far we just have a bunch of code sitting on our computer and if someone else wants to use our code, they need to copy all the files and folders. 

Let's "build" the project.

```bash
poetry build
```

This will take all your code, bundle it, and put it in a versioned file inside of a `/dist/` folder. The file should look something like this: `test-package-0.1.0.tar.gz`.

It will also create a wheel file for you that looks something like this: `test_package-0.1.0-py3-none-any.whl`

## 5. Testing your code in other virtual environments 
Now what I like to do is test my package in a brand new virtual environment. 

Create a new virtual env in a new folder somewhere else on your computer.
```bash
mkdir testenv && cd testenv 
python3 -m venv .venv/ 
source .venv/bin/activate 
```

> Note: Your virtual env will be created differently if you're on Windows. You can use virtualenv, pipenv, Docker, etc. It just needs to be a fresh environment. 

Now that you're in a new Python environment, copy that .tar.gz from from earlier into this folder. (I usually use the operating systems OS for this, but there's nothing wrong with using `cp` to copy the file). The only file in this virtual environment should be your .tar.gz file. 

Now install this file with:
```bash
pip install test-package-0.1.0.tar.gz
```

Assuming everything went well, let's test this out. 

Open a new Python shell (REPL) with:
`python` (on non-Windows) or `py` on Windows. And type this out:

```python
from test_package.myfile import custom_function

custom_function("Kalob")
```

It should print out `Hello Kalob!`.

And just like that, you have create a bundled package. But it's not available for everybody just yet.

## 6. Push it to GitHub 
At this stage I like to push my code up to GitHub. 

Because we're making a public package, I tend to make my repo's public as well. No use hiding the source code when it will be easily downloaded from PyPi.org anyway. 

Dont forget to add `/dist/` and other files to your .gitignore file. The `/dist/` folder is where your bundled code goes when it's built by Poetry. 

## 7. Publish the package 
Now let's publish this code on PyPi.org. 

First, you need a free [PyPi.org](https://pypi.org/) account.  You'll need your username and password handy because Poetry will ask for it so it can upload your file to PyPi and associate it with your account. 

Once you have a free PyPi account, go ahead and run this in your terminal:

```bash 
poetry publish
```

It will ask for your username and password. Go ahead and type those in. 

And now your package will be on PyPi.org. 

> **Note**: If the package of `test-package` already exists, or at one point existed, on PyPi.org you _cannot_ use the same name. Making your Python packages have unique names is the best way to avoid this problem. 

If you didn't run into a naming problem, you'll have successfully published a package to PyPi.org! 

Congrats!

## 8. Install your package using pip
Assuming your package is now on PyPi, let's install your package in another project and test it out. 

```bash
pip install test-package
```

Everything should work as expected now. And your code is now easily accessible to every Python developer. 🎉 

## Example repo 
If you'd like to see a simple package I recently created for [Arbington.com](https://arbington.com) take a look at [python-vimeo on GitHub](https://github.com/arbington/python-vimeo) and feel free to use any part of that repo. That's why we open sourced it! :)