CLI app without python after install from pip

Viewed 434

I have seen a few examples of python packages that, after installing from something like pypi, have CLIs associated with the tooling.

Two examples: rasa (e.g. rasa init) or streamlit (e.g. streamlit hello).

I am interested in exploring this for my own packages, with my requirement that I do not want to preface my commands with python. For example, rasa init as shown above, not python rasa init, but admittedly I have no idea how this is happening under the hood.

2 Answers

entry_points or scripts are used for this.

Here's the relevant piece of streamlit's setup.py:

setuptools.setup(
    ...
    entry_points={"console_scripts": ["streamlit = streamlit.cli:main"]},
    ...
    # For Windows so that streamlit * commands work ie.
    # - streamlit version
    # - streamlit hello
    scripts=["bin/streamlit.cmd"],
)

Interestingly, some sources seem to claim that entry_points doesn't work on Windows, while others claim that it is scripts that doesn't work on Windows. Personally I've always been using entry_points and it works for me both on Windows 10 and on Linux.

This guide may be of help

Here's one of my simple setup.py to illustrate how I did it.

The scripts= option allow you to specify where the script(s) are. When you install it, then these scripts will be included in the paths allowing you to run them.

The scripts should be:

  1. Executable chmod +x
  2. Have a python shebang #!/usr/bin/env python
  3. It is also best practices to have a __name__ == __main__ part of the code

To test it, you can build it and install it in a virtualenv

python setup.py sdist bdist_wheel  # This will build the tar.gz (identical to what pypi uses)
virtualenv venv  # Create an env so you don't mess your setups
source venv/bin/activate  # Activate environment
pip install -e dist/<package_name>-<version>.tar.gz  # This installs it in the venv

pip list should show it's installed

If installation is successful your script should be available. On Mac, it's which script_name. The path will point to the venv.

Related