Python Apps the Right Way: entry points and scripts

There are multiple ways to write an app in Python. However, not all of them
provide your users with the best experience.

One of the problems some people encounter is writing launch scripts. The
best way to handle this is the Entry Points mechanism of Setuptools, and a
__main__.py file. It’s quite easy to implement. If you’re interested,
read on to learn more!

Requirements and Desired Results

You will need:

(entry_points_project is also where the README and other auxiliary files
go, while my_project contains all the Python code.)

When you’re done, you will have a project that can be executed by:

  • python -m my_project
  • my_project

Provided that you have your Python directory and its Scripts subdirectory on
the %PATH%, this will also work in Windows.

Step 1: create a __main__.py file

In order to implement the first desired result, you need to create a
__main__.py file in your package. This file needs to contain a main()
function that takes no arguments, and also a special passage to determine code
to run:

entry_points_project/my_project/__main__.py

import sys


def main(args=None):
    """The main routine."""
    if args is None:
        args = sys.argv[1:]

    print("This is the main routine.")
    print("It should do something interesting.")

    # Do argument parsing here (eg. with argparse) and anything else
    # you want your project to do.

if __name__ == "__main__":
    main()
  1. The if __name__ == "__main__": idiom, as documented here, is used to check whether
    this is executed as the top-level file, or if it has been imported by someone
    else (in this case, executing the main() function is not always intended).
  2. The main() function must not take any arguments, because that’s how
    entry_points executes things.

Step 2: adjust setup.py accordingly

This is the real deal: create the entry points in your setup.py file.

entry_points_project/setup.py

from setuptools import setup

setup(name='my_project',
      version='0.1.0',
      packages=['my_project'],
      entry_points={
          'console_scripts': [
              'my_project = my_project.__main__:main'
          ]
      },
      )
  1. You must use setuptools, otherwise this won’t work.
  2. The most important piece of code is the entry_points declaration
    (unsurprisingly).
  3. The declaration reads
"name_of_executable = module.with:function_to_execute"
  1. If you are developing a GUI application (in Tkinter, PyQt/PySide,
    WxPython, PyGTK, PyGame…), you should change the declaration to
    gui_scripts.
  2. You can create multiple scripts this way. You can also have multiple
    console_scripts and gui_scripts in one setup file.

All code samples are Copyright © 2014 Chris Warrick and licensed
under CC-BY 3.0.