Simple guide to packaging python applications

This will be mostly a self-note for the future, and from someone who packaged an application for the first time today. I did get it working though, so here’s how I did it. I will try to use the correct terms to refer to stuff, but please excuse any mistakes. This works in Linux, I didn’t test anything on Windows and Mac OS X.

The method I’ll present should work for any simple package with no obscure requirements. It will allow you to package an app in PyPI with some data files bundled, required dependencies and a script file so your users can run your code. It’ll also create a tarball with everything bundled inside. Your users will be a “pip install” away from running your code.

Let’s start with the directory structure and go over each file.

appname
├── LICENSE
├── README
├── MANIFEST.in
├── setup.py
├── bin
│   └── appname
└── appname
    ├── __init__.py
    ├── appname.py
    └── data
        └── config
            └── config.yaml

LICENSE - You should have a license. You can use WTFPL if you don’t care about such issues, or use something more restrictive like GPL or whatever, but license it. People won’t use your code if they don’t know that they can use it.

README - Write a description about your application, what it does, how to use it, how to contribute. Stuff.

MANIFEST.in - This file is used to auto generate another called MANIFEST (without the .in). You can use it for more things, I just use it to include extra files in the tarball. Example:

include LICENSE README
recursive-include appname/data/config *

setup.py - This is the main configuration file. Example:

from setuptools import setup
setup(
    name = "appname",
    packages = ["appname"],
    scripts = ["bin/appname"],
    include_package_data = True,
    package_data = {
        "appname":
        [
            "appname/data/config/config.yaml",
        ]
    },
    version = "0.1.0",
    description = "My App",
    author = "My Name",
    author_email = "[email protected]",
    url = "https://github.com/myname/myapp",
    download_url = "https://github.com/myname/myapp/zipball/master",
    keywords = ["my", "awesome", "app"],
    install_requires=[
        "package1 >= 1.4.1",
        "package2 == 0.8.9",
    ],
    license='LICENSE',
    classifiers = [
        "Programming Language :: Python",
        "Development Status :: 2 - Pre-Alpha",
        "Environment :: Other Environment",
        "Intended Audience :: Developers",
        "License :: Public Domain",
        "Operating System :: POSIX :: Linux",
        "Topic :: Software Development",
        ],
    long_description = open('README').read()
)

bin/appname - An executable file which will be placed in /usr/local/bin so your users can call your application from anywhere. Example:

#!/usr/bin/python
import appname.appname as appname

if __name__ == "__main__":
    appname.main()

appname/__init__.py - This file is necessary so Python recognizes this directory as containing a package. You can leave it empty.

appname.py - Where your code lives. Make sure you have a main() or equivalent, as called by the bin/ script.

data/ - Additional files. These can be images, config files, databases or whatever your application needs to function properly. There’s no requirement here, just make sure you add them correctly on setup.py and on MANIFEST.in

Now that you have everything set up go over to PyPI, register yourself and run this in your command line:

python setup.py register sdist upload

Hopefully, if you typed everything correctly and I haven’t missed anything, your application will be packaged and uploaded to PyPI. Make sure you choose a name that’s available for your package!

I don’t claim this will work for more than my environment but it worked for me (Linux Ubuntu 11.04).

More information about packaging:

  1. http://getpython3.com/diveintopython3/packaging.html
  2. http://guide.python-distribute.org/index.html
  3. http://docs.python.org/distutils/setupscript.html