Package a Python Project and Make it Available via pip install: Simple Example
Last updated:Here is an example project built following the instructions on this post: Python Data Science Utils
For more information on what terms like pip, virtualenv, etc., mean see Python Environment Cheatsheet
sample setup.py file
File setup.py
is the most important configuration file for your project. Here is an example to get you started:
# -*- coding: utf-8 -*-
import setuptools
with open("README.md", "r") as fh:
long_description = fh.read()
setuptools.setup(
name="myproject",
version="0.0.1", # Update this for every new version
author="Your name",
author_email="your@email.com",
description="long description",
long_description=long_description,
long_description_content_type="text/markdown",
install_requires=[ # Add project dependencies here
"pandas>=0.20.0" # example: pandas version 0.20 or greater
],
url="https://github.com/your/github/project",
packages=setuptools.find_packages(),
classifiers=( # Classifiers help people find your
"Programming Language :: Python :: 3", # projects. See all possible classifiers
"License :: OSI Approved :: MIT License", # in https://pypi.org/classifiers/
"Operating System :: OS Independent",
),
)
Project Structure
project-name/ <--- project name, does not need to match the inner name
│
├── myproject <--- module name, this is the name you'll use in "import"
│ ├── __init__.py <--- init file must be here, even if your project is Python 3 only
│ └── module.py <--- submodules
│
├── LICENSE <--- optional but recommended
│
├── README.md
│
└── setup.py <--- package information. name, author, version, and DEPENDENCIES
Package the project
To package the project, run python setup.py sdist bdist_wheel
(preferably under a virtualenv):
(test-venv)$ python setup.py sdist bdist_wheel
running sdist
running egg_info
creating myproject.egg-info
writing requirements to myproject.egg-info/requires.txt
...
...
After running the packaging commands, your project should now look like this:
project-name/
│
├── build
│ ├── bdist.linux-x86_64
│ └── lib
│ └── myproject
│ ├── __init__.py
│ └── module.py
├── dist <--- this is the directory that
│ ├── myproject-0.0.1-py3-none-any.whl will get uploaded to pypi
│ └── myproject-0.0.1.tar.gz
│
├── LICENSE
│
├── myproject
│ ├── __init__.py
│ └── module.py
│
├── myproject.egg-info
│ ├── dependency_links.txt
│ ├── PKG-INFO
│ ├── SOURCES.txt
│ └── top_level.txt
│
├── README.md
│
└── setup.py
Upload project to PyPi
Trying to upload the
myproject
project will fail because someone has already created a project on PyPi with that name!
To upload the project you need a tool called twine
, which can be installed with pip:
(test-venv)$ pip install twine
Collecting twine
...
...
At this point, you should register an account on pypi.org so that you can upload packages.
After you created your account, you can upload the packaged files using: twine upload dist/*
The error message is expected because the name already exists. You should pick a unique project name.
(test-venv)$ twine upload dist/*
Uploading distributions to https://upload.pypi.org/legacy/
Enter your username: xxxxx
Enter your password:
Uploading myproject-0.0.1-py3-none-any.whl
100%|████████████████████████████████████████████████████████| 4.52k/4.52k [00:00<00:00, 5.46kB/s]
HTTPError: 403 Client Error: The user 'xxxxx' isn't allowed to upload to project 'MyProject'.
See https://pypi.org/help/#project-name for more information. for url: https://upload.pypi.org/legacy/
Congratulations! After uploading the project (as above), anyone can install your project via pip.
Troubleshooting
Can't import module
If you can't import the module you just uploaded, make sure you have an __init__.py
file as in the instructions, even if your project is full Python 3!
Module 'pkg_resources' has no attribute 'iter_entry_points'
Force reinstall setuptools
:
(venv)$ pip install --upgrade --force-reinstall setuptools
This short post is part of the Data Newsletter. Click here to sign up.