6.3. OS Commandline Arguments
6.3.1. Alternatives
Check
colorama
- coloring terminal output
6.3.2. Typer
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
https://docs.python.org/3/library/argparse.html#the-add-argument-method
Define how a single command-line argument should be parsed.
6.3.5. Parser parameters
prog |
The name of the program (default: |
---|---|
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 |
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 |
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 = ...