TLDR: How to Publish to PyPI
Published on
Have you ever asked yourself how to publish your Python package, so you can install it using pip? It is less complex than it seems, and anyone can do it.
The first step is to create an account on the Python Package Index (PyPI) were all Python packages are registered.
After that, you need to create a file called setup.py
on the root folder of the Python code that you will publish with the following content, changing the values were is needed:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from setuptools import find_packages, setup
setup(
name='my-python-package',
packages=find_packages(),
version='1.0.0',
description='Short description of your package',
long_description='Long description of your package',
author='Your name',
author_email='my@email.com',
url='https://github.com/user/my-python-package',
install_requires=['dependency1', 'dependency2'],
license='MIT',
keywords=['dev', 'web'],
classifiers=[
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Natural Language :: English',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 3',
],
)
The find_packages
function is an excellent tool to discover the files that compose your package automatically. You can check its docs right here.
The classifiers
are used to help users to find your package by indexing it into several categories, and you can look to the complete list following this link.
Packaging
Before publishing your package, you need to package it first, and the easiest way to do that is running:
$ python setup.py sdist
To package it with a pre-compiled code you need to run:
$ python setup.py bdist_wheel
Done that, you will have everything packed up inside the folder dist/
.
Publishing
To publish your package, you will need to install twine. It is a tool to publish packages at the PyPI:
$ pip install twine
After installed run the following command:
$ twine upload --username pypi-username dist/my-package-1.0.0.tar.gz dist/my-package-1.0.0-py2-none-any.whl dist/my-package-1.0.0-py3-none-any.whl
The command will ask for your password, and then, it will upload it to the PyPI.
Bonus - Versioning
A common practice is to keep the package version and another package information inside the __init__.py
file like this:
__author__ = 'My Name'
__email__ = 'my@email.com'
__version__ = '1.0.0'
You can add the following code at the setup.py
to use this info from the __init__.py
at your package:
import os
import re
package = 'my_package'
with open(os.path.join(package, '__init__.py'), 'rb') as f:
init_py = f.read().decode('utf-8')
version = re.search(
'^__version__ = [\'\"]([^\'\"]+)[\'\"]', init_py, re.MULTILINE
).group(1)
author = re.search(
'^__author__ = [\'\"]([^\'\"]+)[\'\"]', init_py, re.MULTILINE
).group(1)
email = re.search(
'^__email__ = [\'\"]([^\'\"]+)[\'\"]', init_py, re.MULTILINE
).group(1)
...
setup(
...
version=version,
author=author,
author_email=email,
...
)
Bonus - README.md as long_description
If you use github you probably write a readme file to describe your package. You can use it as your long_description
, so you don’t need to repeat yourself:
with open('README.md', 'rb') as f:
readme = f.read().decode('utf-8')
setup(
...
long_description=readme,
long_description_content_type="text/markdown",
...
)
This work is licensed under a Creative Commons Attribuition-ShareAlike 4.0 International License .