Command Line Scripts ==================== Many Python packages include command line tools. This is useful for distributing support tools which are associated with a library, or just taking advantage of the setuptools / PyPI infrastructure to distribute a command line tool that happens to use Python. For **funniest**, we'll add a ``funniest-joke`` command line tool. There are two mechanisms that ``setuptools.setup()`` provides to do this: the ``scripts`` keyword argument, and the ``console_scripts`` entry point. The ``scripts`` Keyword Argument ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The first approach is to write your script in a separate file, such as you might write a shell script.:: funniest/ funniest/ __init__.py ... setup.py bin/ funniest-joke ... The ``funniest-joke`` script just looks like this:: #!/usr/bin/env python import funniest print funniest.joke() Then we can declare the script in ``setup()`` like this:: setup( ... scripts=['bin/funniest-joke'], ... ) When we install the package, setuptools will copy the script to our PATH and make it available for general use.:: $ funniest-joke This has advantage of being generalizeable to non-python scripts, as well: ``funniest-joke`` could be a shell script, or something completely different. The ``console_scripts`` Entry Point ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The second approach is called an 'entry point'. Setuptools allows modules to register entrypoints which other packages can hook into to provide certain functionality. It also provides a few itself, including the ``console_scripts`` entry point. This allows Python *functions* (not scripts!) to be directly registered as command-line accessible tools. In this case, we'll add a new file and function to support the command line tool:: funniest/ funniest/ __init__.py command_line.py ... setup.py ... The ``command_line.py`` submodule exists only to service the command line tool (which is a convenient organization method):: import funniest def main(): print funniest.joke() You can test the "script" by running it directly, e.g.:: $ python >>> import funniest.command_line >>> funniest.command_line.main() ... The ``main()`` function can then be registered like so:: setup( ... entry_points = { 'console_scripts': ['funniest-joke=funniest.command_line:main'], } ... ) Again, once the package has been installed, we can use it in the same way. Setuptools will generate a standalone script 'shim' which imports your module and calls the registered function. This method has the advantage that it's very easily testable. Instead of having to shell out to spawn the script, we can have a test case that just does something like:: from unittest import TestCase from funniest.command_line import main class TestConsole(TestCase): def test_basic(self): main() In order to make that more useful, we'll probably want something like a context manager which temporarily captures ``sys.stdout``, but that is outside the scope of this tutorial.