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.

Looking for a project template?

If you want to create a well-structured project with release automation and some other goodies, check out my Python Project Template.

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 (Source)

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. Return values are exit codes.
if __name__ == "__main__":
    sys.exit(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 (Source)

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. On *nix, this makes no difference, but on Windows, it means that running your script by opening the created .exe files does not show a console window. Note that stdout/stderr do not work in that mode under Windows, which can lead to spurious application crashes. (GUI-only processes cannot use stdout/stderr because they don’t have a console attached)

  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 freely reusable, but if you mention where you got them from, it’d be really nice.