Skip to content

Multiple CLI Options

You can declare a CLI option that can be used multiple times, and then get all the values.

For example, let's say you want to accept several users in a single execution.

For this, use the standard Python typing.List to declare it as a list of str:

from typing import List, Optional

import typer
from typing_extensions import Annotated


def main(user: Annotated[Optional[List[str]], typer.Option()] = None):
    if not user:
        print(f"No provided users (raw input = {user})")
        raise typer.Abort()
    for u in user:
        print(f"Processing user: {u}")


if __name__ == "__main__":
    typer.run(main)
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from typing import List, Optional

import typer


def main(user: Optional[List[str]] = typer.Option(None)):
    if not user:
        print(f"No provided users (raw input = {user})")
        raise typer.Abort()
    for u in user:
        print(f"Processing user: {u}")


if __name__ == "__main__":
    typer.run(main)

You will receive the values as you declared them, as a list of str.

Check it:

// The default value is 'None'
$ python main.py

No provided users (raw input = None)
Aborted!

// Now pass a user
$ python main.py --user Camila

Processing user: Camila

// And now try with several users
$ python main.py --user Camila --user Rick --user Morty

Processing user: Camila
Processing user: Rick
Processing user: Morty

Multiple float

The same way, you can use other types and they will be converted by Typer to their declared type:

from typing import List

import typer
from typing_extensions import Annotated


def main(number: Annotated[List[float], typer.Option()] = []):
    print(f"The sum is {sum(number)}")


if __name__ == "__main__":
    typer.run(main)
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from typing import List

import typer


def main(number: List[float] = typer.Option([])):
    print(f"The sum is {sum(number)}")


if __name__ == "__main__":
    typer.run(main)

Check it:

$ python main.py

The sum is 0

// Try with some numbers
$ python main.py --number 2

The sum is 2.0

// Try with some numbers
$ python main.py --number 2 --number 3 --number 4.5

The sum is 9.5

Passing multiple values in a single argument

Typer supports passing multiple arguments with a single option, by using the separator parameter in combination with typing.List[T] types. This feature makes it easy to parse multiple values from a single command-line argument into a list in your application.

To use this feature, define a command-line option that accepts multiple values separated by a specific character (such as a comma). Here's an example of how to implement this:

=== "Python 3.7+"

```Python hl_lines="7"

```

=== "Python 3.7+ non-Annotated"

!!! tip
    Prefer to use the `Annotated` version if possible.

```Python hl_lines="6"

```

Check it:

// With no optional CLI argument
$ python main.py

The sum is 0

// With one number argument
$ python main.py --number 2

The sum is 2.0

// With several number arguments, split using the separator defined by the Option argument
$ python main.py --number "2, 3, 4.5"

The sum is 9.5

// You can remove the quotes if no whitespace is added between the numbers
$ python main.py --number 2,3,4.5

The sum is 9.5

// Supports passing the option multiple times. This joins all values to a single list
$ python main.py --number 2,3,4.5 --number 5

The sum is 14.5

!!! warning Only single-character non-whitespace separators are supported.