One of the great advantages of Python is the ecosystem of thousands of packages that you can easily add functionality to a project – and these packages are very easy to install – just:
pip install package_name
In this tutorial we’ll see how to create a package and upload it to PyPi (soon to be renamed / relaunched as Warehouse), so that rather than needing to git clone your package from github, other people can just
pip install your_package too!
This is intended to be a bare minimum crib sheet, but I’ll reference more details along the way – and you can always read the official guide here.
1. Folder & File Structure
The absolute minimum folder and file structure is:
|-- arbitrary_folder_name | |-- package_name | | |-- __init__.py | |-- LICENSE | |-- README.md | |-- setup.cfg | |-- setup.py
– Note that the root folder on your computer (rbitrary_folder_name) can be an any name – the name of the plugin should reflect the folder INSIDE this (package_name).
– It’s good practice to supply a license so users of your code know how they can use it. Github created choosealicense.com with some standard licenses you can use.
– README file – see below for how to use a Markdown readme.
2. Packaging details in setup.py
setup.py is the the place where the package is defined. Apart from the obvious items pay attention to:
- name: must be unique accross all pypi packages. Do
pip search package_nameto list any existing packages of the name (if any). Read the docs for info on what names are considered identical.
- packages: list of all top level packages within the main folder, (including but not necessarily just the name of the package)
- long_description: This is the main description people will see on warehouse / pypi. Obviously its likely you’ll just want to use the README file, but pypi currently only supports ReStructured text, and is awaiting a feature to add Markdown (which most people use as Github displays this automatically). I’ve written a little conversion function (get_readme()) which uses an online service instead of needing to install another module.
- version: most obvious choice is Major.Minor.Maintenance e.g. ‘1.0.0’, More details of what that means here.
- url: web link to your project code aka github or other code repo
- classifiers: some info about your project which helps people when browsing on pypi, such as maturity of the project, Python versions supported, up to you how much info you add – see more details here.
- install_requires: This should be a list immediate dependencies your package requires – i.e. the ones you package directly imports, NOT including dependencies of dependencies. If like me you use a python virtualenv for all your projects it’s worth knowing that it’s not best practice to just use the output of pip freeze, so your env folder and requirements.txt are not needed in packaging for upload to pypi – see why here. Just need to find a way of automating that without using pip freeze!
3. Test and Build Package
Check all tests run ok:
python setup.py test
Build the package: this will create a folder named dist – note if you’re using githubs standard python .gitignore this is excluded from your git repo (since it can be built from the source).
python setup.py sdist
4. Register at Pypi / Warehouse and Upload Package
Firstly you’ll need to register and both pypi and the test pypi site. It’s really useful to havea test site as there are always things that don’t quite work first time, and with pypi you cannot upload the same version number twice – so if you have a small error in your packaging then you’ll have to up-rev the version number, which looks like you’re making code changes. So it’s best to get everything working on testpypi first before uploading to the official pypi site. Secondly, you need to install the twine package which helps to upload your package to pypi.
pip install twine
twine upload --repository-url https://test.pypi.org/legacy/ dist/* # test repo
If that’s successful you can create a new virtualenv, and install form the test pypi:
pip install -i https://testpypi.python.org/pypi package_name
Finally, once you’re happy with the package, make sure to rebuild the package (with the correct version number) and then upload to the official pypi / warehouse site:
twine upload dist/* # defaults to actual repo
5. More complicated stuff
If you’re doing something a little more complicated such as adding documentation or compiled C code there some good tips in this article.