6.3. OS Commandline Arguments

6.3.1. Alternatives

  • Check colorama - coloring terminal output

6.3.2. Typer

  • https://typer.tiangolo.com

  • Typer is library for building CLI applications that users will love using and developers will love creating. Based on Python 3.6+ type hints.

  • The key features are:

    • Intuitive to write: Great editor support. Completion everywhere. Less time debugging. Designed to be easy to use and learn. Less time reading docs.

    • Easy to use: It's easy to use for the final users. Automatic help, and automatic completion for all shells.

    • Short: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs.

    • Start simple: The simplest example adds only 2 lines of code to your app: 1 import, 1 function call.

    • Grow large: Grow in complexity as much as you want, create arbitrarily complex trees of commands and groups of subcommands, with options and arguments.

$ pip install typer
import typer

app = typer.Typer()


@app.command()
def hello(name: str):
    typer.echo(f"Hello {name}")


@app.command()
def goodbye(name: str, formal: bool = False):
    if formal:
        typer.echo(f"Goodbye Ms. {name}. Have a good day.")
    else:
        typer.echo(f"Bye {name}!")


if __name__ == "__main__":
    app()

You have 2 subcommands (the 2 functions): goodbye and hello:

$ python main.py --help
Usage: main.py [OPTIONS] COMMAND [ARGS]...

Options:
  --install-completion  Install completion for the current shell.
  --show-completion     Show completion for the current shell, to copy it or customize the installation.
  --help                Show this message and exit.

Commands:
  goodbye
  hello

Now get the --help for hello:

$ python main.py hello --help

Usage: main.py hello [OPTIONS] NAME

Options:
  --help  Show this message and exit.

And now get the --help for goodbye. Automatic --formal and --no-formal for the bool option:

$ python main.py goodbye --help

Usage: main.py goodbye [OPTIONS] NAME

Options:
  --formal / --no-formal
  --help                  Show this message and exit.

And if you use it with the hello command:

$ python main.py hello Camila
Hello Camila

# And with the goodbye command
$ python main.py goodbye Camila
Bye Camila!

# And with --formal
$ python main.py goodbye --formal Camila
Goodbye Ms. Camila. Have a good day.

6.3.3. docopt

6.3.4. argparse

6.3.5. Parser parameters

prog

The name of the program (default: sys.argv[0])

usage

A usage message (default: auto-generated from arguments)

description

A description of what the program does

epilog

Text following the argument descriptions

parents

Parsers whose arguments should be copied into this one

formatter_class

HelpFormatter class for printing help messages

prefix_chars

Characters that prefix optional arguments

fromfile_prefix_chars

Characters that prefix files containing additional arguments

argument_default

The default value for all arguments

conflict_handler

String indicating how to handle conflicts

add_help

Add a -h/-help option

allow_abbrev

Allow long options to be abbreviated unambiguously

6.3.6. Argument parameters

parameter

description

name or flags

Either a name or a list of option strings, e.g. foo or -f, --foo

action

The basic type of action to be taken when this argument is encountered at the command line

nargs

The number of command-line arguments that should be consumed

const

A constant value required by some action and nargs selections

default

The value produced if the argument is absent from the command line

type

The type to which the command-line argument should be converted

choices

A container of the allowable values for the argument

required

Whether or not the command-line option may be omitted (optionals only)

help

A brief description of what the argument does

metavar

A name for the argument in usage messages

dest

The name of the attribute to be added to the object returned by parse_args()

6.3.7. Simple parsing

import argparse

parser = argparse.ArgumentParser()

parser.add_argument('--numbers', nargs='*', default=[1, 2.5, 3.0], type=float)

args = parser.parse_args()

print(args)
print(args.numbers)

6.3.8. Advanced parameter parsing

import argparse


parser = argparse.ArgumentParser(
    prog='PROGRAM NAME',
    description='A foo that bars',
    epilog="And that's how you'd foo a bar")

parser.add_argument('--sum', dest='accumulate', action='store_const', const=sum,
                    default=max, help='sum the integers (default: find the max)')

parser.add_argument('--foo', nargs='?', help='foo help')
parser.add_argument('--bar', nargs='+', help='bar help')
parser.add_argument('--foobar', nargs='*', default=[1, 2, 3], help='BAR!')

parser.add_argument('--integers', metavar='int',
    type=int, choices=range(10), nargs='+',
    help='an integer in the range 0..9')

parser.add_argument('--baz', nargs='?', type=int, default=42,
    help='the bar to %(prog)s (default: %(default)s)')

parser.add_argument('--move', choices=['rock', 'paper', 'scissors'])

parser.add_argument('--length', default=10, type=int, required=True)
parser.add_argument('--width', default=10.5, type=float)

script_arguments = parser.parse_args()
print(script_arguments)

6.3.9. File handling

import argparse


parser = argparse.ArgumentParser()

parser.add_argument('--input', default='input.csv', type=argparse.FileType('r'))
parser.add_argument('--output', default='output.c', type=argparse.FileType('w'))

args = parser.parse_args()

with args.input as input, args.output as output:
    content = input.read()
    # do conversion
    output.write(content)

6.3.10. Examples

import argparse
import sys
import logging


def read(filename):
    try:
        with open(filename) as file:
            return file.read()

    except FileNotFoundError:
        logging.critical('File does not exists')
        sys.exit(127)


parser = argparse.ArgumentParser()
parser.add_argument('--file', default='/tmp/input.csv', type=read)
args = parser.parse_args()
print(args)
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--file', default='/tmp/input.csv', type=argparse.FileType('r'))

try:
    args = parser.parse_args()

except SystemExit:
    print('File does not exists')

print(args)

6.3.11. docopt

"""Naval Fate.

Usage:
  naval_fate.py ship new <name>...
  naval_fate.py ship <name> move <x> <y> [--speed=<kn>]
  naval_fate.py ship shoot <x> <y>
  naval_fate.py mine (set|remove) <x> <y> [--moored | --drifting]
  naval_fate.py test (true|false)
  naval_fate.py (-h | --help)
  naval_fate.py --version

Options:
  -h --help     Show this screen.
  --version     Show version.
  --speed=<kn>  Speed in knots [default: 10].
  --moored      Moored (anchored) mine.
  --drifting    Drifting mine.

"""
from docopt import docopt


if __name__ == '__main__':
    arguments = docopt(__doc__, version='Naval Fate 2.0')
    print(arguments)

    test = arguments.get('test', None)
    print(test)

# python doc.py test on

# {'--drifting': False,
#  '--help': False,
#  '--moored': False,
#  '--speed': '10',
#  '--version': False,
#  '<name>': [],
#  '<x>': None,
#  '<y>': None,
#  'mine': False,
#  'move': False,
#  'new': False,
#  'off': False,
#  'on': True,
#  'remove': False,
#  'set': False,
#  'ship': False,
#  'shoot': False,
#  'test': True}

6.3.12. Assignments

# FIXME: Write tests
# FIXME: Write solution

# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author

# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`

# %% About
# - Name: Argument parsing
# - Difficulty: easy
# - Lines: 5
# - Minutes: 13

# %% English
# 1. Write a script that will parse command line arguments
# 2. It should accept only `int` and `float`
# 3. For arguments it should run `avg()` function from the listing below:
# 4. Run `python argparse_avg.py --numbers 5 10 100 32 -90 27.5`
# 5. Run doctests - all must pass

# %% Polish
# 1. Napisz parser parametrów linii poleceń
# 2. Ma przyjmować tylko `int` i `float`
# 3. Dla parametrów ma uruchomić funkcje `avg()` z listingu poniżej:
# 4. Uruchamianie `python argparse_avg.py --numbers 5 10 100 32 -90 27.5`
# 5. Uruchom doctesty - wszystkie muszą się powieść

# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'
"""

# %% SetUp
def avg(*args):
    return sum(args) / len(args)


result = ...