Python Packaging: define an entry point for console commands

Packaging is a standard best practice to organize code libraries and functionality for reusability and modularity.  For developers new to the python ecosystem, pypi - http://pypi.python.org/ – is where all the good (open source) stuff are available.

Most of us are familiar with the standard packaging practices using `setup.py` and pip.  We know that using a python library is often as simple as running the `pip install [libraryname]` command in your python environment, after which the library will be downloaded into your machine and the `setup.py` in the said library will run.  Once successfully completed, the installed library will be available for us to `import` in our project’s custom python code.  The typical `setup.py` file looks like this:-

from distutils.core import setup

setup(
    name='My Fabulous Library',
    version='1.1.0',
    packages=['my_fabulous_library', ],
    license='LICENSE',
    description='This powerful python package will cure all your ailments! Save yourself today!',
    long_description=open('README.md').read(),
    author='Calvin Cheng',
    author_email='calvin@calvinx.com',
    install_requires=['other_dependency_a', 'other_dependency_b'],
)

and is located in the root directory of your python package.  Easy peasy and nothing magical here as most of these are described here - http://docs.python.org/dev/packaging/introduction.html – among many other alternative tutorials.

Defining our custom console command

What is less known is the use case where we want to introduce a console (i.e. command-line) level functionality in our library.   What that means is that after we installed our python library, we will actually have additional commands in our python environment in the terminal.

Doing this for our python package is actually trivial once you learn about the `entry_points` attribute in setup.py.  Here’s how it looks like in a code example:-

from distutils.core import setup

setup(
    name='My Fabulous Library',
    version='1.1.0',
    packages=['my_fabulous_library', ],
    license='LICENSE',
    description='This powerful python package will cure all your ailments! Save yourself today!',
    long_description=open('README.md').read(),
    author='Calvin Cheng',
    author_email='calvin@calvinx.com',
    install_requires=['other_dependency_a', 'other_dependency_b'],
    entry_points={
        'console_scripts': [
            'myspecialcommand = my_fabulous_library.main:main',
        ]
    }
)

By specifying thus, a “myspecialcommand” file will be created with permissions 755 in your machine’s python environment’s “bin” directory when `setup.py` runs (during a pip install) and the “myspecialcommand” command will become available to you in the command line.

This special file  points to your actual python `main` function which you should write in your `my_fabulous_library/main.py` file.

When you type “myspecialcommand” now, it will essentially execute the main() function and you can add in any custom functionality you now need in your main() function in your main.py file from now on.  As usual, if you have written standalone python console scripts before, you will know that `optparse` module is your friend and you can parse any optional arguments provided to your command line function by using `optparse` in your main() function.

Defining an entry point for your python package/library is really trivial now that you are familiar with this standard code layout/configuration in your `setup.py` file.  Have fun!