Declaring types moves validation out of your code and gives users precise error messages.
Every parameter has a type that converts the raw string and validates it. Built-ins beyond int, float, bool and str:
click.Choice(["json", "csv"], case_sensitive=False): one of a fixed set, shown in help. Since 8.2 it also accepts anEnumclass, and your function receives the enum member.click.IntRange(1, 10)/click.FloatRange(0, 1): numbers within bounds;clamp=Trueclips instead of failing.click.Path(exists=True, file_okay=True, dir_okay=False, path_type=pathlib.Path): validates a filesystem path and returns aPathobject if you ask.click.File("r")/click.File("wb"): opens the file for you, supports-for stdin/stdout, and closes it when the command finishes. Output files are opened lazily, so a failed command does not leave empty files.click.DateTime(formats=[...]),click.UUID, and tuples of types such astype=(str, int)withnargs=2.
When conversion fails, Click prints a usage error such as Error: Invalid value for '--level': 12 is not in the range 1<=x<=10. and exits with code 2. Your function never runs with invalid data.
Choosing Path versus File: use File for simple read/write of one stream, especially when supporting -. Use Path when you need the path itself (directories, passing to other libraries, opening several times).
Environment variables and prompts go through the same types, so validation is consistent wherever the value comes from.
Example
import enum
import pathlib
import click
class Fmt(enum.Enum):
JSON = "json"
CSV = "csv"
@click.command()
@click.option("--fmt", type=click.Choice(Fmt, case_sensitive=False), default="json")
@click.option("--level", type=click.IntRange(1, 10), default=5)
@click.option("--src", type=click.Path(exists=True, dir_okay=False, path_type=pathlib.Path))
@click.option("--out", type=click.File("w"), default="-")
def export(fmt, level, src, out):
out.write(f"{fmt} level={level} src={src}\n")
export.main(["--fmt", "CSV", "--level", "3"], standalone_mode=False)
# Fmt.CSV level=3 src=None
try:
export.main(["--level", "12"], standalone_mode=False)
except click.BadParameter as e:
print(e.format_message())
# Invalid value for '--level': 12 is not in the range 1<=x<=10.Remember
- Choice, IntRange, Path and File validate and convert input
- Invalid values fail with a clear usage error before your code runs
- File handles '-' and closes files; Path gives you the path
Watch out for
- Opening files manually from a str option instead of using click.File or click.Path validation.