CLI Arguments with Environment Variables
You can also configure a CLI argument to read a value from an environment variable if it is not provided in the command line as a CLI argument.
To do that, use the envvar
parameter for typer.Argument()
:
import typer
from typing_extensions import Annotated
def main(name: Annotated[str, typer.Argument(envvar="AWESOME_NAME")] = "World"):
print(f"Hello Mr. {name}")
if __name__ == "__main__":
typer.run(main)
Tip
Prefer to use the Annotated
version if possible.
import typer
def main(name: str = typer.Argument("World", envvar="AWESOME_NAME")):
print(f"Hello Mr. {name}")
if __name__ == "__main__":
typer.run(main)
In this case, the CLI argument name
will have a default value of "World"
, but will also read any value passed to the environment variable AWESOME_NAME
if no value is provided in the command line:
// Check the help
$ python main.py --help
Usage: main.py [OPTIONS] [NAME]
Arguments:
[NAME] [env var: AWESOME_NAME;default: World]
Options:
--help Show this message and exit.
// Call it without a CLI argument
$ python main.py
Hello Mr. World
// Now pass a value for the CLI argument
$ python main.py Czernobog
Hello Mr. Czernobog
// And now use the environment variable
$ AWESOME_NAME=Wednesday python main.py
Hello Mr. Wednesday
// CLI arguments take precedence over env vars
$ AWESOME_NAME=Wednesday python main.py Czernobog
Hello Mr. Czernobog
Multiple environment variables¶
You are not restricted to a single environment variable, you can declare a list of environment variables that could be used to get a value if it was not passed in the command line:
import typer
from typing_extensions import Annotated
def main(
name: Annotated[str, typer.Argument(envvar=["AWESOME_NAME", "GOD_NAME"])] = "World"
):
print(f"Hello Mr. {name}")
if __name__ == "__main__":
typer.run(main)
Tip
Prefer to use the Annotated
version if possible.
import typer
def main(name: str = typer.Argument("World", envvar=["AWESOME_NAME", "GOD_NAME"])):
print(f"Hello Mr. {name}")
if __name__ == "__main__":
typer.run(main)
Check it:
// Check the help
$ python main.py --help
Usage: main.py [OPTIONS] [NAME]
Arguments:
[NAME] [env var: AWESOME_NAME, GOD_NAME;default: World]
Options:
--help Show this message and exit.
// Try the first env var
$ AWESOME_NAME=Wednesday python main.py
Hello Mr. Wednesday
// Try the second env var
$ GOD_NAME=Anubis python main.py
Hello Mr. Anubis
Hide an env var from the help text¶
By default, environment variables used will be shown in the help text, but you can disable them with show_envvar=False
:
import typer
from typing_extensions import Annotated
def main(
name: Annotated[
str, typer.Argument(envvar="AWESOME_NAME", show_envvar=False)
] = "World"
):
print(f"Hello Mr. {name}")
if __name__ == "__main__":
typer.run(main)
Tip
Prefer to use the Annotated
version if possible.
import typer
def main(name: str = typer.Argument("World", envvar="AWESOME_NAME", show_envvar=False)):
print(f"Hello Mr. {name}")
if __name__ == "__main__":
typer.run(main)
Check it:
//Check the help
$ python main.py --help
// It won't show the env var
Usage: main.py [OPTIONS] [NAME]
Arguments:
[NAME] [default: World]
Options:
--help Show this message and exit.
// But it will still be able to use it
$ AWESOME_NAME=Wednesday python main.py
Hello Mr. Wednesday
Technical Details
In Click applications the env vars are hidden by default. 🙈
In Typer these env vars are shown by default. 👀