typer README

The project's README from github.com/fastapi/typer. As one markdown file: README.md.

Typer

Typer, build great CLIs. Easy to code. Based on Python type hints.

Test Coverage Package version


Documentation: https://typer.tiangolo.com

Source Code: https://github.com/fastapi/typer


Typer is a library for building CLI applications that users will love using and developers will love creating. Based on Python type hints.

It's also a command line tool to run scripts, automatically converting them to CLI applications.

The key features are:

FastAPI of CLIs

Typer is FastAPI's little sibling, it's the FastAPI of CLIs.

Installation

First, install uv, and then add Typer to your project:

$ uv add typer
---> 100%

This installs both the Typer library and the typer command in the project's virtual environment. To use typer directly with shell completion, activate the project environment and install completion.

If you prefer to use pip, install typer inside a virtual environment. See the installation guide for the alternative steps.

Example

The absolute minimum

def main(name: str):
    print(f"Hello {name}")

This script doesn't even use Typer internally. But you can use the typer command to run it as a CLI application.

Run it

Run your application with the typer command:

// Run your application
$ typer main.py run

// You get a nice error, you are missing 'name'
Usage: typer [PATH_OR_MODULE] run [OPTIONS] {name}
Try 'typer [PATH_OR_MODULE] run --help' for help.
╭─ Error ───────────────────────────────────────────╮
│ Missing argument 'name'.                          │
╰───────────────────────────────────────────────────╯


// You get a --help for free
$ typer main.py run --help

Usage: typer [PATH_OR_MODULE] run [OPTIONS] {name}

Run the provided Typer app.

╭─ Arguments ───────────────────────────────────────╮
│ *    name      <str>  [required]                  │
╰───────────────────────────────────────────────────╯
╭─ Options ─────────────────────────────────────────╮
│ --help          Show this message and exit.       │
╰───────────────────────────────────────────────────╯

// Now pass the 'name' argument
$ typer main.py run Camila

Hello Camila

// It works! 🎉

This is the simplest use case, not even using Typer internally, but it can already be quite useful for simple scripts.

Note: auto-completion works when you create a Python package and run it with --install-completion or when you use the typer command.

Use Typer in your code

Now let's start using Typer in your own code, update main.py with:

import typer


def main(name: str):
    print(f"Hello {name}")


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

Now you could run it with Python directly:

// Run your application
$ uv run python main.py

// You get a nice error, you are missing 'name'
Usage: main.py [OPTIONS] {name}
Try 'main.py --help' for help.
╭─ Error ───────────────────────────────────────────╮
│ Missing argument 'name'.                          │
╰───────────────────────────────────────────────────╯


// You get a --help for free
$ uv run python main.py --help

Usage: main.py [OPTIONS] {name}

╭─ Arguments ───────────────────────────────────────╮
│ *    name      <str>  [required]                  │
╰───────────────────────────────────────────────────╯
╭─ Options ─────────────────────────────────────────╮
│ --help          Show this message and exit.       │
╰───────────────────────────────────────────────────╯

// Now pass the 'name' argument
$ uv run python main.py Camila

Hello Camila

// It works! 🎉

Note: you can also call this same script with the typer command, but you don't need to.

Example upgrade

This was the simplest example possible.

Now let's see one a bit more complex.

An example with two subcommands

Modify the file main.py.

Create a typer.Typer() app, and create two subcommands with their parameters.

import typer

app = typer.Typer()


@app.command()
def hello(name: str):
    print(f"Hello {name}")


@app.command()
def goodbye(name: str, formal: bool = False):
    if formal:
        print(f"Goodbye Ms. {name}. Have a good day.")
    else:
        print(f"Bye {name}!")


if __name__ == "__main__":
    app()

And that will:

Run the upgraded example

Check the new help:

$ uv run 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 ────────────────────────────────────────╮
│ hello                                             │
│ goodbye                                           │
╰───────────────────────────────────────────────────╯

// When you create a package you get ✨ auto-completion ✨ for free, installed with --install-completion

// You have 2 subcommands (the 2 functions): hello and goodbye

Now check the help for the hello command:

$ uv run python main.py hello --help

 Usage: main.py hello [OPTIONS] {name}

╭─ Arguments ───────────────────────────────────────╮
│ *    name      <str>  [required]                  │
╰───────────────────────────────────────────────────╯
╭─ Options ─────────────────────────────────────────╮
│ --help          Show this message and exit.       │
╰───────────────────────────────────────────────────╯

And now check the help for the goodbye command:

$ uv run python main.py goodbye --help

 Usage: main.py goodbye [OPTIONS] {name}

╭─ Arguments ───────────────────────────────────────╮
│ *    name      <str>  [required]                  │
╰───────────────────────────────────────────────────╯
╭─ Options ─────────────────────────────────────────╮
│ --formal    --no-formal      [default: no-formal] │
│ --help                       Show this message    │
│                              and exit.            │
╰───────────────────────────────────────────────────╯

// Automatic --formal and --no-formal for the bool option 🎉

Now you can try out the new command line application:

// Use it with the hello command

$ uv run python main.py hello Camila

Hello Camila

// And with the goodbye command

$ uv run python main.py goodbye Camila

Bye Camila!

// And with --formal

$ uv run python main.py goodbye --formal Camila

Goodbye Ms. Camila. Have a good day.

Note: If your app only has one command, by default the command name is omitted in usage: python main.py Camila. However, when there are multiple commands, you must explicitly include the command name: python main.py hello Camila. See One or Multiple Commands for more details.

Recap

In summary, you declare once the types of parameters (CLI arguments and CLI options) as function parameters.

You do that with standard modern Python types.

You don't have to learn a new syntax, the methods or classes of a specific library, etc.

Just standard Python.

For example, for an int:

total: int

or for a bool flag:

force: bool

And similarly for files, paths, enums (choices), etc. And there are tools to create groups of subcommands, add metadata, extra validation, etc.

You get: great editor support, including completion and type checks everywhere.

Your users get: automatic --help, auto-completion in their terminal (Bash, Zsh, Fish, PowerShell) when they install your package or when using the typer command.

For a more complete example including more features, see the Tutorial - User Guide.

Dependencies

Typer requires only a few dependencies (most are tiny):

Click code

Typer used to depend on Click as well, a popular tool for building CLIs in Python.

Since version 0.26.0, Typer has vendored Click (included Click's source code internally, instead of installing it as a third party package) and has unified the code interactions between Typer and the embedded Click source code for easier maintainability in the future.

Note that some Click functionality will not be available anymore in the future, as we continue to improve and extend Typer's codebase.

typer-slim

There used to be a slimmed-down version of Typer called typer-slim, which didn't include the dependencies rich and shellingham, nor the typer command.

However, since version 0.22.0, we have stopped supporting this, and typer-slim now simply installs (all of) Typer.

If you want to disable Rich globally, you can set an environmental variable TYPER_USE_RICH to False or 0.

License

This project is licensed under the terms of the MIT license.

typer (fastapi/typer)

Searching Database…

20.1K ·GitHub
这是什么?Typer 是一个用来构建命令行应用的 Python 库:你只需编写普通的 Python 函数,用标准的类型注解声明参数,就能得到一个完善的命令行工具,自动带帮助信息和命令补全。
它是我导入的库,还是在终端里运行的工具?两者都是。你可以在 Python 代码中导入 Typer 来定义命令行应用,这个包还自带 typer 命令,可以把任何 Python 脚本当命令行工具运行——哪怕脚本完全没用到 Typer 也行。
怎么把它加到我的项目里?先安装 uv,然后运行 'uv add typer'——这会把 Typer 库和 typer 命令一起装进项目的虚拟环境。如果你更喜欢用 pip,也可以在虚拟环境里安装 typer。
它会不会给我的项目拖进来一大堆依赖?不会,只有几个小包:rich 用于美观的错误输出,shellingham 用于检测你当前使用的 shell,annotated-doc 用于从注解生成文档,Windows 上还有 colorama。Click 不再单独安装——从 0.26.0 起,它的代码已经内置在 Typer 里了。
当我的应用有多个命令之后,该怎么运行它?只有一个命令时,命令名可以省略:python main.py Camila。有多个命令时,就必须显式写上命令名:python main.py hello Camila。
我可以在商业项目里使用它吗?可以——Typer 采用 MIT 许可证,可以自由使用和分发,包括用在商业软件里。
最简单的 Typer 应用长什么样?两行代码:一个 import 和一次函数调用。脚本内部甚至不需要用到 Typer——typer 命令照样能把它当命令行应用运行。
怎么构建一个带多个子命令的应用?创建一个 typer.Typer() 应用,给每个函数加上 @app.command() 装饰器,最后调用 app()。每个函数就变成了一个子命令,还可以把子命令组合成任意复杂的命令树。
为什么它被称为命令行工具界的 FastAPI?Typer 是 FastAPI 的小兄弟,两者核心理念相同:用标准的现代 Python 类型来声明参数——int、bool、文件、路径、用于选项的枚举——无需学习任何库专属语法,就能获得编辑器补全、类型检查和参数校验。
用 Typer 构建的应用,用户能获得 shell 补全吗?能:在 Bash、Zsh、Fish 和 PowerShell 中自动提供 --help 帮助和 Tab 自动补全,无论是用户安装你的包时,还是通过 typer 命令运行它时。
Creator
fastapi
Size
4 MB
Stars
20.1K
Age
6y
Commits · 90 Days