๐ฌ It just prints "Hello World". ๐ฌ Now check the --helppython main.py --help Usage: main.py [OPTIONS] โญโ Options โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ โ --help Show this message โ โ and exit. โ โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
fast โpython main.py ๐ฌ If you run it without the argument, it shows a nice errorUsage: main.py [OPTIONS] NAME Try 'main.py --help' for help. โญโ Error โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ โ Missing argument 'NAME'. โ โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
๐ฌ Now pass that NAME CLI argumentpython main.py Camila Hello Camila
๐ฌ Here "Camila" is the CLI argument ๐ฌ To pass a name with spaces for the same CLI argument, use quotespython main.py "Camila Gutiรฉrrez" Hello Camila Gutiรฉrrez
fast โ๐ฌ Check the main --helppython main.py --help Usage: main.py [OPTIONS] NAME Try 'main.py --help' for help. โญโ Error โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ โ Missing argument 'NAME'. โ โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
typer on ๎ richify[ยป!?] via ๐ v3.7.5 (env3.7) โฏ python main.py Usage: main.py [OPTIONS] NAME LASTNAME Try 'main.py --help' for help. โญโ Error โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ โ Missing argument 'NAME'. โ โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
๐ฌ There are now 2 CLI arguments, name and lastname ๐ฌ Now pass a single name argumentpython main.py Camila Usage: main.py [OPTIONS] NAME LASTNAME Try 'main.py --help' for help. โญโ Error โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ โ Missing argument 'LASTNAME'. โ โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
๐ฌ These 2 arguments are required, so, pass both:python main.py Camila Gutiรฉrrez Hello Camila Gutiรฉrrez
Notice that the order is important. The last name has to go after the first name.
If you called it with:
$ python main.py Gutiรฉrrez Camila
your app wouldn't have a way to know which is the name and which the lastname. It expects the first CLI argument to be the name and the second CLI argument to be the lastname.
Here we will use the word CLI option to refer to CLI parameters passed to the CLI application with a specific name. For example, if you go to your terminal and type:
fast โls ./myproject --size 12 first-steps.md 4 intro.md
The main visual difference between a CLI option and a CLI argument is that the CLI option has -- prepended to the name, like in "--size".
A CLI option doesn't depend on the order because it has a predefined name (here it's --size). This is because the CLI app is looking specifically for a literal --size parameter (also known as "flag" or "switch"), with that specific "name" (here the specific name is "--size"). The CLI app will check if you typed it or not, it will be actively looking for --size even if you didn't type it (to check if it's there or not).
In contrast, the CLI app is not actively looking for the CLI argument with a text "./myproject", it has no way to know if you would type ./myproject or ./my-super-awesome-project or anything else. It's just waiting to get whatever you give it. The only way to know that you refer to a specific CLI argument is because of the order. The same way that it knows that the first CLI argument was the name and the second was the lastname, but if you mixed the order, it wouldn't be able to handle it.
Instead, with a CLI option, the order doesn't matter.
Also, by default, a CLI option is optional (not required).
So, by default:
A CLI argument is required
A CLI option is optional
But the required and optional defaults can be changed.
So, the main and most important difference is that:
CLI optionsstart with -- and don't depend on the order
CLI arguments depend on the sequence order
Tip
In this example above the CLI option--size is just a "flag" or "switch" that will contain a boolean value, True or False, depending on if it was added to the command or not.
This one doesn't receive any values. But CLI options can also receive values like CLI arguments. You'll see how later.
importtyperdefmain(name:str,lastname:str,formal:bool=False):ifformal:print(f"Good day Ms. {name}{lastname}.")else:print(f"Hello {name}{lastname}")if__name__=="__main__":typer.run(main)
Here formal is a bool that is False by default.
fast โ๐ฌ Get the helppython main.py --help Usage: main.py [OPTIONS] NAME LASTNAME โญโ Arguments โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ โ * name TEXT [default: None] [required] โ โ * lastname TEXT [default: None] [required] โ โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ โญโ Options โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ โ --formal--no-formal [default: no-formal] โ โ --help Show this message and โ โ exit. โ โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
To convert the lastname from a CLI argument to a CLI option, give it a default value of "":
importtyperdefmain(name:str,lastname:str="",formal:bool=False):ifformal:print(f"Good day Ms. {name}{lastname}.")else:print(f"Hello {name}{lastname}")if__name__=="__main__":typer.run(main)
As lastname now has a default value of "" (an empty string) it is no longer required in the function, and Typer will now by default make it an optional CLI option.
fast โpython main.py --help Usage: main.py [OPTIONS] NAME โญโ Arguments โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ โ * name TEXT [default: None] [required] โ โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ โญโ Options โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ โ --lastnameTEXT โ โ --formal--no-formal [default: no-formal] โ โ --help Show this message โ โ and exit. โ โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
Notice the --lastname, and notice that it takes a textual value.
A CLI option with a value like --lastname (contrary to a CLI option without a value, a bool flag, like --formal or --size) takes as its value whatever is at the right side of the CLI option.
fast โ๐ฌ Call it without a --lastnamepython main.py Camila Hello Camila
If you add a docstring to your function it will be used in the help text:
importtyperdefmain(name:str,lastname:str="",formal:bool=False):""" Say hi to NAME, optionally with a --lastname. If --formal is used, say hi very formally. """ifformal:print(f"Good day Ms. {name}{lastname}.")else:print(f"Hello {name}{lastname}")if__name__=="__main__":typer.run(main)
Now see it with the --help option:
fast โpython main.py --help Usage: main.py [OPTIONS] NAME Say hi to NAME, optionally with a --lastname. If --formal is used, say hi very formally.
โญโ Arguments โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ โ * name TEXT [default: None] [required] โ โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ โญโ Options โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ โ --lastnameTEXT โ โ --formal--no-formal [default: no-formal] โ โ --help Show this message โ โ and exit. โ โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
There is another place to document the specific CLI options and CLI arguments that will show up next to them in the help text as with --install-completion or --help, you will learn that later in the tutorial.
When talking about command line interface applications, the words "argument" and "parameter" are commonly used to refer to that data passed to a CLI app, those parameters.
But those words don't imply anything about the data being required, needing to be passed in a certain order, nor having a flag like --lastname.
The parameters that come with a name like --lastname (and optionally a value) are commonly optional, not required. So, when talking about CLIs it's common to call them optional arguments or optional parameters. Sometimes these optional parameters that start with -- are also called a flag or a switch.
In reality, the parameters that require an order can be made optional too. And the ones that come with a flag (like --lastname) can be required too.