Create python command line in few lines, and use it anywhere as a standalone tool!

python
cli
typer
Creating python command line could be useful for a lot of tools. Traditionally, argparse has been used heavily, a new library called typer leverage python type hint, that makes creating command line interface in Python much pleasant.
Author

noklam

Published

December 10, 2020

The Typer documentation has great example explaining how to use it. This is the example copied from their GitHub homepage. https://github.com/tiangolo/typer.

import typer


def main(name: str):
    typer.echo(f"Hello {name}")


if __name__ == "__main__":
    typer.run(main)
Overwriting main1.py
!python main1.py world
Hello world
!python main1.py --help
Usage: main1.py [OPTIONS] NAME

Arguments:
  NAME  [required]

Options:
  --install-completion [bash|zsh|fish|powershell|pwsh]
                                  Install completion for the specified shell.
  --show-completion [bash|zsh|fish|powershell|pwsh]
                                  Show completion for the specified shell, to
                                  copy it or customize the installation.

  --help                          Show this message and exit.

Here I write a new file to main1.py and execute it as a command line with just 5 lines of code. It always comes with a help message for free. Let’s see another example.

import typer


def main(name: str, age: int = 20, height_meters: float = 1.89, female: bool = True):
    typer.echo(f"NAME is {name}, of type: {type(name)}")
    typer.echo(f"--age is {age}, of type: {type(age)}")
    typer.echo(f"--height-meters is {height_meters}, of type: {type(height_meters)}")
    typer.echo(f"--female is {female}, of type: {type(female)}")


if __name__ == "__main__":
    typer.run(main)
Writing main2.py
!python main2.py --help
Usage: main2.py [OPTIONS] NAME

Arguments:
  NAME  [required]

Options:
  --age INTEGER                   [default: 20]
  --height-meters FLOAT           [default: 1.89]
  --female / --no-female          [default: True]
  --install-completion [bash|zsh|fish|powershell|pwsh]
                                  Install completion for the specified shell.
  --show-completion [bash|zsh|fish|powershell|pwsh]
                                  Show completion for the specified shell, to
                                  copy it or customize the installation.

  --help                          Show this message and exit.

This time, we can see that the help message even supplement the expected datatype. Typer will validate the type and conevrt it when possible.

!python main2.py Nok --age=3
NAME is Nok, of type: <class 'str'>
--age is 3, of type: <class 'int'>
--height-meters is 1.89, of type: <class 'float'>
--female is True, of type: <class 'bool'>

The command line works file, but it only works in the same directory, and you always have to type the keyword python. With python setuptools, we can actually installed a command line and run it anywhere. It is pretty easy with just 1 trick, let’s go back to the simple Hello command.

import typer

def hello(name:str):
    typer.echo(f"Hello {name}")
    
def main():
    typer.run(hello)
Overwriting main3.py

Here we made a few changes. 1. The logic is move to a new function named hello 2. We removed the __main__ part, as we will not call this python file directly anymore. 3. typer.run(main) is changed to typer.run(hello) and moved inside the main function.

Console Script

We will use setuptool to build console script, which may call the function main. The magic is using console script to install a command line interface (It creates a .exe file) that can be run anywhere. We can name our command line instead of using the filename with a pattern of command_name=file:func_name. Here our function main is inside a file main3.py, so we use hello=main3:main.

from setuptools import setup, find_packages


setup(
    name="my_library",
    version="1.0",
    packages=find_packages(),
        entry_points = {
        'console_scripts': ['hello=main3:main']}
)
Overwriting setup.py

Then we install the console script .

!python setup.py develop
!hello world
Hello world

We can now call hello anywhere, as it is installed as a executable.

!where hello
C:\ProgramData\Miniconda3\Scripts\hello.exe

It’s time for you to build your own commands. This can be easily extended to support multiple commands. https://github.com/tiangolo/typer