跳至内容

入门

最简单的示例

最简单的Typer文件可能如下所示

import typer


def main():
    print("Hello World")


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

将其复制到文件main.py中。

测试它

$ python main.py

Hello World

// It just prints "Hello World".

// Now check the --help
$ python main.py --help

<b> </b><font color="#F4BF75"><b>Usage: </b></font><b>main.py [OPTIONS]                            </b>
<b>                                                     </b>
<font color="#A5A5A1">╭─ Options ─────────────────────────────────────────╮</font>
<font color="#A5A5A1">│ </font><font color="#A1EFE4"><b>--help</b></font>                        Show this message   │
<font color="#A5A5A1">│                               and exit.           │</font>
<font color="#A5A5A1">╰───────────────────────────────────────────────────╯</font>

...但此程序仍然不太有用。让我们扩展它。

什么是CLI 参数

此处我们将使用术语CLI 参数来指按特定顺序传递给 CLI 应用程序的CLI 参数。默认情况下,它们是必需的

如果你转到你的终端并键入

$ ls ./myproject

first-steps.md  intro.md

ls 将显示目录 ./myproject 的内容。

  • ls程序(或“命令”、“CLI 应用程序”)。
  • ./myproject 是一个CLI 参数,在此处它指一个目录的路径。

它们与你稍后在下面看到的CLI 选项略有不同。

添加一个 CLI 参数

使用参数 name 更新上一个示例

import typer


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


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

// If you run it without the argument, it shows a nice error
<font color="#F4BF75">Usage: </font>main.py [OPTIONS] NAME
<font color="#A5A5A1">Try </font><font color="#44919F">&apos;main.py </font><font color="#44919F"><b>--help</b></font><font color="#44919F">&apos;</font><font color="#A5A5A1"> for help.</font>
<font color="#F92672">╭─ Error ───────────────────────────────────────────╮</font>
<font color="#F92672">│</font> Missing argument &apos;NAME&apos;.                          <font color="#F92672">│</font>
<font color="#F92672">╰───────────────────────────────────────────────────╯</font>

// Now pass that NAME CLI argument
$ python main.py Camila

Hello Camila

// Here "Camila" is the CLI argument

// To pass a name with spaces for the same CLI argument, use quotes
$ python main.py "Camila Gutiérrez"

Hello Camila Gutiérrez

提示

如果你需要将包含空格的单个值传递给CLI 参数,请在其周围使用引号 (")。

两个 CLI 参数

现在假设我们想要将名字和姓氏分开。

因此,将其扩展为具有 2 个参数,namelastname

import typer


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


if __name__ == "__main__":
    typer.run(main)
// Check the main --help
$ python main.py --help

<font color="#F4BF75">Usage: </font>main.py [OPTIONS] NAME
<font color="#A5A5A1">Try </font><font color="#44919F">&apos;main.py </font><font color="#44919F"><b>--help</b></font><font color="#44919F">&apos;</font><font color="#A5A5A1"> for help.</font>
<font color="#F92672">╭─ Error ───────────────────────────────────────────╮</font>
<font color="#F92672">│</font> Missing argument &apos;NAME&apos;.                          <font color="#F92672">│</font>
<font color="#F92672">╰───────────────────────────────────────────────────╯</font>

<font color="#A1EFE4"><b>typer</b></font> on <font color="#AE81FF"><b> richify</b></font> <font color="#F92672"><b>[»!?] </b></font>via <font color="#F4BF75"><b>🐍 v3.7.5 (env3.7)</b></font>
<font color="#F92672"><b>❯</b></font> <font color="#A6E22E">python</font> <u style="text-decoration-style:single">main.py</u>
<font color="#F4BF75">Usage: </font>main.py [OPTIONS] NAME LASTNAME
<font color="#A5A5A1">Try </font><font color="#44919F">&apos;main.py </font><font color="#44919F"><b>--help</b></font><font color="#44919F">&apos;</font><font color="#A5A5A1"> for help.</font>
<font color="#F92672">╭─ Error ───────────────────────────────────────────╮</font>
<font color="#F92672">│</font> Missing argument &apos;NAME&apos;.                          <font color="#F92672">│</font>
<font color="#F92672">╰───────────────────────────────────────────────────╯</font>

// There are now 2 CLI arguments, name and lastname

// Now pass a single name argument
$ python main.py Camila

<font color="#F4BF75">Usage: </font>main.py [OPTIONS] NAME LASTNAME
<font color="#A5A5A1">Try </font><font color="#44919F">&apos;main.py </font><font color="#44919F"><b>--help</b></font><font color="#44919F">&apos;</font><font color="#A5A5A1"> for help.</font>
<font color="#F92672">╭─ Error ───────────────────────────────────────────╮</font>
<font color="#F92672">│</font> Missing argument &apos;LASTNAME&apos;.                      <font color="#F92672">│</font>
<font color="#F92672">╰───────────────────────────────────────────────────╯</font>

// These 2 arguments are required, so, pass both:
$ python main.py Camila Gutiérrez

Hello Camila Gutiérrez

提示

请注意,顺序很重要。姓氏必须放在名字之后。

如果你使用以下命令调用它

$ python main.py Gutiérrez Camila

你的应用程序将无法知道哪个是 name,哪个是 lastname。它期望第一个CLI 参数name,第二个CLI 参数lastname

什么是CLI 选项

此处我们将使用术语CLI 选项来指使用特定名称传递给 CLI 应用程序的CLI 参数。例如,如果你转到你的终端并键入

$ ls ./myproject --size

12 first-steps.md   4 intro.md

ls 将显示目录 ./myproject 的内容及其大小

  • ls程序(或“命令”、“CLI 应用程序”)。
  • ./myproject 是一个CLI 参数
  • --size 是一个可选的CLI 选项

该程序知道它必须显示大小,因为它看到了 --size,而不是因为顺序。

--size 这样的CLI 选项不依赖于像CLI 参数那样的顺序。

因此,如果你将 --size 放在CLI 参数之前,它仍然有效(事实上,这是最常见的方法)

$ ls --size ./myproject

12 first-steps.md   4 intro.md

CLI 选项CLI 参数之间的主要视觉差异在于CLI 选项在名称前加有--,如“--size”。

CLI 选项不依赖于顺序,因为它有一个预定义的名称(此处为--size)。这是因为 CLI 应用程序专门查找带有该特定“名称”(此处特定名称为“--size”)的文字--size参数(也称为“标志”或“开关”)。CLI 应用程序将检查您是否键入了它,即使您没有键入它,它也会主动查找--size(以检查它是否存在)。

相比之下,CLI 应用程序不会主动查找带有“./myproject”文本的CLI 参数,它无法知道您会键入./myproject还是./my-super-awesome-project或其他任何内容。它只是等待获取您给它的任何东西。知道您指的是特定CLI 参数的唯一方法是通过顺序。它知道第一个CLI 参数name,第二个是lastname,但如果您混淆了顺序,它将无法处理它。

相反,使用CLI 选项,顺序无关紧要。

此外,默认情况下,CLI 选项可选的(不是必需的)。

所以,默认情况下

  • CLI 参数必需的
  • CLI 选项可选的

必需的可选的默认值可以更改。

所以,主要且最重要的区别是

  • CLI 选项--开头且不依赖于顺序
  • CLI 参数依赖于顺序顺序

提示

在上面的示例中,CLI 选项--size只是一个“标志”或“开关”,它将包含布尔值TrueFalse,具体取决于它是否已添加到命令中。

这个不接收任何值。但CLI 选项也可以接收值,如CLI 参数。稍后您将看到。

添加一个CLI 选项

现在添加一个--formalCLI 选项

import typer


def main(name: str, lastname: str, formal: bool = False):
    if formal:
        print(f"Good day Ms. {name} {lastname}.")
    else:
        print(f"Hello {name} {lastname}")


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

此处formal是一个默认值为Falsebool

// Get the help
$ python main.py --help

<b> </b><font color="#F4BF75"><b>Usage: </b></font><b>main.py [OPTIONS] NAME LASTNAME                            </b>
<b>                                                                   </b>
<font color="#A5A5A1">╭─ Arguments ─────────────────────────────────────────────────────╮</font>
<font color="#A5A5A1">│ </font><font color="#F92672">*</font>    name          <font color="#F4BF75"><b>TEXT</b></font>  [default: None] <font color="#A6194C">[required]</font>             │
<font color="#A5A5A1">│ </font><font color="#F92672">*</font>    lastname      <font color="#F4BF75"><b>TEXT</b></font>  [default: None] <font color="#A6194C">[required]</font>             │
<font color="#A5A5A1">╰─────────────────────────────────────────────────────────────────╯</font>
<font color="#A5A5A1">╭─ Options ───────────────────────────────────────────────────────╮</font>
<font color="#A5A5A1">│ </font><font color="#A1EFE4"><b>--formal</b></font>                <font color="#AE81FF"><b>--no-formal</b></font>      [default: no-formal]   │
<font color="#A5A5A1">│ </font><font color="#A1EFE4"><b>--help</b></font>                                   Show this message and  │
<font color="#A5A5A1">│                                          exit.                  │</font>
<font color="#A5A5A1">╰─────────────────────────────────────────────────────────────────╯</font>

提示

请注意,它会自动创建一个--formal和一个--no-formal,因为它检测到formal是一个bool

现在正常调用它

$ python main.py Camila Gutiérrez

Hello Camila Gutiérrez

// But if you pass --formal
$ python main.py Camila Gutiérrez --formal

Good day Ms. Camila Gutiérrez.

// And as --formal is a CLI option you can put it anywhere in this command
$ python main.py Camila --formal Gutiérrez

Good day Ms. Camila Gutiérrez.

$ python main.py --formal Camila Gutiérrez

Good day Ms. Camila Gutiérrez.

带值的CLI 选项

要将lastnameCLI 参数转换为CLI 选项,请为其指定默认值""

import typer


def main(name: str, lastname: str = "", formal: bool = False):
    if formal:
        print(f"Good day Ms. {name} {lastname}.")
    else:
        print(f"Hello {name} {lastname}")


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

由于lastname现在具有默认值""(空字符串),因此函数中不再需要它,并且Typer现在默认将其设为可选CLI 选项

$ python main.py --help

<b> </b><font color="#F4BF75"><b>Usage: </b></font><b>main.py [OPTIONS] NAME                                       </b>
<b>                                                                     </b>
<font color="#A5A5A1">╭─ Arguments ───────────────────────────────────────────────────────╮</font>
<font color="#A5A5A1">│ </font><font color="#F92672">*</font>    name      <font color="#F4BF75"><b>TEXT</b></font>  [default: None] <font color="#A6194C">[required]</font>                   │
<font color="#A5A5A1">╰───────────────────────────────────────────────────────────────────╯</font>
<font color="#A5A5A1">╭─ Options ─────────────────────────────────────────────────────────╮</font>
<font color="#A5A5A1">│ </font><font color="#A1EFE4"><b>--lastname</b></font>                             <font color="#F4BF75"><b>TEXT</b></font>                       │
<font color="#A5A5A1">│ </font><font color="#A1EFE4"><b>--formal</b></font>                <font color="#AE81FF"><b>--no-formal</b></font>    <font color="#F4BF75"><b>    </b></font>  [default: no-formal] │
<font color="#A5A5A1">│ </font><font color="#A1EFE4"><b>--help</b></font>                                 <font color="#F4BF75"><b>    </b></font>  Show this message    │
<font color="#A5A5A1">│                                              and exit.            │</font>
<font color="#A5A5A1">╰───────────────────────────────────────────────────────────────────╯</font>

提示

注意--lastname,并注意它采用文本值。

一个值类似于 --lastnameCLI 选项(与没有值的CLI 选项相反,一个 bool 标志,如 --formal--size)将其值作为CLI 选项右侧的任何内容。

// Call it without a --lastname
$ python main.py Camila

Hello Camila

// Pass the --lastname
$ python main.py Camila --lastname Gutiérrez

Hello Camila Gutiérrez

提示

请注意,“Gutiérrez”位于 --lastname 的右侧。一个有值的CLI 选项将其值作为右侧的任何内容。

并且由于 --lastname 现在是一个不依赖于顺序的CLI 选项,因此可以在名称之前传递它

$ python main.py --lastname Gutiérrez Camila

// and it will still work normally
Hello Camila Gutiérrez

记录你的 CLI 应用程序

如果你向你的函数添加一个文档字符串,它将用于帮助文本中

import typer


def main(name: str, lastname: str = "", formal: bool = False):
    """
    Say hi to NAME, optionally with a --lastname.

    If --formal is used, say hi very formally.
    """
    if formal:
        print(f"Good day Ms. {name} {lastname}.")
    else:
        print(f"Hello {name} {lastname}")


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

现在使用 --help 选项查看它

$ python main.py --help

<b> </b><font color="#F4BF75"><b>Usage: </b></font><b>main.py [OPTIONS] NAME                                       </b>
<b>                                                                     </b>
 Say hi to NAME, optionally with a <font color="#A1EFE4"><b>--lastname</b></font>.
 If <font color="#6B9F98"><b>--formal</b></font><font color="#A5A5A1"> is used, say hi very formally.                          </font>

<font color="#A5A5A1">╭─ Arguments ───────────────────────────────────────────────────────╮</font>
<font color="#A5A5A1">│ </font><font color="#F92672">*</font>    name      <font color="#F4BF75"><b>TEXT</b></font>  [default: None] <font color="#A6194C">[required]</font>                   │
<font color="#A5A5A1">╰───────────────────────────────────────────────────────────────────╯</font>
<font color="#A5A5A1">╭─ Options ─────────────────────────────────────────────────────────╮</font>
<font color="#A5A5A1">│ </font><font color="#A1EFE4"><b>--lastname</b></font>                             <font color="#F4BF75"><b>TEXT</b></font>                       │
<font color="#A5A5A1">│ </font><font color="#A1EFE4"><b>--formal</b></font>                <font color="#AE81FF"><b>--no-formal</b></font>    <font color="#F4BF75"><b>    </b></font>  [default: no-formal] │
<font color="#A5A5A1">│ </font><font color="#A1EFE4"><b>--help</b></font>                                 <font color="#F4BF75"><b>    </b></font>  Show this message    │
<font color="#A5A5A1">│                                              and exit.            │</font>
<font color="#A5A5A1">╰───────────────────────────────────────────────────────────────────╯</font>

提示

还有另一个地方可以记录特定的CLI 选项CLI 参数,这些选项和参数将在帮助文本中显示在它们旁边,如 --install-completion--help,你将在本教程的后面部分了解到这一点。

参数、选项、参数、可选、必需

请注意,这些术语根据上下文指代多个事物,遗憾的是,这些“上下文”经常混合,因此很容易混淆。

在 Python 中

在 Python 中,函数中变量的名称,如 namelastname

def main(name: str, lastname: str = ""):
    pass

被称为“Python 函数参数”或“Python 函数参数”。

技术细节

实际上,Python 中的“参数”和“参数”之间有一个非常小的区别。

这非常技术化……而且有点迂腐。

参数指函数声明中的变量名称。如

def bring_person(name: str, lastname: str = ""):
    pass

参数调用函数时传递的值。如

person = bring_person("Camila", lastname="Gutiérrez")

... 但你可能会看到它们在大多数地方(包括这里)互换使用。

Python 默认值

在 Python 中,在函数中,一个具有默认值的参数(如 lastname

def main(name: str, lastname: str = ""):
    pass

被视为“可选参数”(或“可选参数”)。

默认值可以是任何值,如 ""None

而一个没有默认值的参数(如 name)则被视为必需的

在 CLI 中

在讨论命令行界面应用程序时,单词“参数”“参数”通常用于指传递给 CLI 应用程序的数据,这些参数。

但这些单词并不暗示有关数据是必需的、需要按特定顺序传递或具有 --lastname 之类的标志的任何信息。

带有 --lastname(以及可选值)名称的参数通常是可选的,不是必需的。因此,在讨论 CLI 时,通常将它们称为可选参数可选参数。有时,这些以 -- 开头的可选参数也称为标志开关

实际上,需要按顺序的参数也可以设为可选。而带有标志(如 --lastname)的参数也可以设为必需

Typer

为了让它更容易一点,我们通常会使用单词“参数”或“参数”来指 Python 函数。

我们将使用CLI 参数来指那些取决于特定顺序的CLI 参数。默认情况下必需

我们将使用CLI 选项来指那些取决于以 -- 开头的名称的CLI 参数(如 --lastname)。默认情况下可选

我们将使用CLI 参数来指两者,CLI 参数CLI 选项

typer 命令

当你安装 typer 时,默认情况下它会向你的 shell 添加一个 typer 命令。

typer 命令允许你在终端中使用 ✨ 自动完成 ✨ 运行脚本。

作为使用 Python 运行的替代方案

$ python main.py

Hello World

你可以使用 typer 命令运行

$ typer main.py run

Hello World

...当您按 TAB 键时,它将在您的终端中为您提供自动完成,适用于您的所有代码。

因此,当您继续学习本教程时,您可以使用它为自己的脚本提供自动完成。

提示

一旦您创建了一个 Python 包,使用 Typer 构建的 CLI 应用程序将不再需要 typer 命令来进行自动完成。

但在创建 Python 包之前,对于短脚本和学习来说,它可能很有用。