Creating Python packages

2019-05-02
Python



pypi_logo

1. Create a python package

To work with python you only need a .py file. However if you are creating a package you need to follow a concrete structure and include some needed files.

Before creating your project, I suggest you check if the name you want to use exists:

pip search package_name

You can also look for it at pypi web

1.1. Structure your project

You should have your project inside a folder with the name of the package. This will be the root of your project and should include .gitignore, README.md and LICENSE.txt among other configuration files.

The code should be inside another folder with the name of the package. So the structure should be:

- /package_name
    ├── /package_name
    │   ├── __init__.py
    │   ├── file1.py
    │   ├── file2.py
    │   └── fileN.py
    ├── .gitignore
    ├── LICENSE.txt
    ├── README.md
    └── setup.py

1.1.1. Main files

All files inside /package_name/package_name should have imports that work from the main path. For example to import the file1 in file2 you should:

from .file1 import my_function

Do not forget the '.' before the name

The __init__.py file will contain whatever you want to call from the 'outside'.

For example:

from .file2 import public_function

This is what will allow you to do the following one you have uploaded the package:

import package_name
package_name.public_function() # This will call the 'public_function' from 'file2.py'

1.1.2. setup.py

This is where you define the package itself, how can it be installed and some basic information about it. A basic example would be:

import io
from setuptools import setup

setup(
    name="package_name",
    version="1.0.2",
    author="Your Name",
    author_email="your@email.com",
    packages=["package_name"],
    install_requires=io.open("requirements.txt", encoding="utf-8").read().splitlines(),
    include_package_data=True,
    license="MIT",
    description=("write here a short description"),
    long_description=io.open("README.md", encoding="utf-8").read(),
    long_description_content_type="text/markdown",
    url="https://github.com/your_user/package_name",
    package_data={"package_name": ["resources/*"]},
)
1.1.2.1. long_description param

long_description is extracted from the README.md

you can use other formats for the README like ost

1.1.2.2. install_requires param

install_requires is a list of requirements. In the example I get it from requirements.txt.

You could also write the requirements by hand with:

install_requires=["pandas>0.22", "flask"]

You should avoid requirements with a fixed number version use < or > instead.

1.1.2.3. package_data param

The package_data parameter allows you to include all files inside /package_name/resources/ path even if they are not .py files. This will be useful if you want to include html templates or yaml/json with data.

1.2. Create the package

Before creating the package I suggest you add some rules in the .gitignore:

build/
dist/
*.egg-info

After that you can run:

python setup.py sdist bdist_wheel

Then you will have build with the content of the package and dist with tar and wheels of the package (what will be uploaded).

2. Upload the package

2.1. Requirements

When you run pip install package you are actually downloading it from pypi. There is also test.pypi for testing purpouses. So you will need to register:

To upload the packages I suggest you use twine. You can install it with:

pip install twine

2.2. Uploading a package to test.pypi

You can run the next command which will upload all packages created in the dist folder:

python -m twine upload --repository-url https://test.pypi.org/legacy/ dist/*

The first time you run this command you will be asked to log in. Use the credentials from the previous step.

After uploading the package you can download it to test if it is working as expected:

pip install --index-url https://test.pypi.org/simple/ package_name

# You can specify the version with
pip install --index-url https://test.pypi.org/simple/ package_name==X.X.X

2.3. Uploading a package to pypi

In order to upload the package to pypi the process is very similar to the step before:

python -m twine upload dist/*

And to install it you can simply run:

pip install package

Well done, you now have your first python package uploaded to pypi.