打印和颜色
你可以使用普通的 print()
在屏幕上显示信息
import typer
def main():
print("Hello World")
if __name__ == "__main__":
typer.run(main)
它将正常显示输出
$ python main.py
Hello World
使用 Rich¶
你还可以使用 Rich 显示美观且更复杂的信息。当你安装 typer
时,它会默认安装。
使用 Rich print
¶
对于最简单的情况,你可以从 rich
导入 print
,然后使用它来代替标准的 print
import typer
from rich import print
data = {
"name": "Rick",
"age": 42,
"items": [{"name": "Portal Gun"}, {"name": "Plumbus"}],
"active": True,
"affiliation": None,
}
def main():
print("Here's the data")
print(data)
if __name__ == "__main__":
typer.run(main)
有了它,Rich 就能以漂亮的颜色和结构打印您的数据
$ python main.py
Here's the data
<b>{</b>
<font color="#A6E22E">'name'</font>: <font color="#A6E22E">'Rick'</font>,
<font color="#A6E22E">'age'</font>: <font color="#A1EFE4"><b>42</b></font>,
<font color="#A6E22E">'items'</font>: <b>[</b>
<b>{</b><font color="#A6E22E">'name'</font>: <font color="#A6E22E">'Portal Gun'</font><b>}</b>,
<b>{</b><font color="#A6E22E">'name'</font>: <font color="#A6E22E">'Plumbus'</font><b>}</b>
<b>]</b>,
<font color="#A6E22E">'active'</font>: <font color="#A6E22E"><i>True</i></font>,
<font color="#A6E22E">'affiliation'</font>: <font color="#AE81FF"><i>None</i></font>
<b>}</b>
Rich 标记¶
Rich 还支持 自定义标记语法 来设置颜色和样式,例如
import typer
from rich import print
def main():
print("[bold red]Alert![/bold red] [green]Portal gun[/green] shooting! :boom:")
if __name__ == "__main__":
typer.run(main)
$ python main.py
<font color="#F92672"><b>Alert!</b></font> <font color="#A6E22E">Portal gun</font> shooting! 💥
在这个示例中,您可以看到如何使用字体样式、颜色,甚至表情符号。
要了解更多信息,请查看 Rich 文档。
Rich 表格¶
Rich 在内部的工作方式是使用 Console
对象来显示信息。
当您调用 Rich 的 print
时,它会自动创建此对象并使用它。
但是对于高级用例,您可以自己创建一个 Console
。
import typer
from rich.console import Console
from rich.table import Table
console = Console()
def main():
table = Table("Name", "Item")
table.add_row("Rick", "Portal Gun")
table.add_row("Morty", "Plumbus")
console.print(table)
if __name__ == "__main__":
typer.run(main)
在此示例中,我们创建了一个 Console
和一个 Table
。然后我们可以向表格中添加一些行,并打印它。
如果您运行它,您将看到一个格式良好的表格
$ python main.py
┏━━━━━━━┳━━━━━━━━━━━━┓
┃<b> Name </b>┃<b> Item </b>┃
┡━━━━━━━╇━━━━━━━━━━━━┩
│ Rick │ Portal Gun │
│ Morty │ Plumbus │
└───────┴────────────┘
Rich 还有许多其他功能,例如,您可以查看以下文档
Typer 和 Rich¶
如果您想知道应该使用什么工具,Typer 对于构建命令行应用程序很有用,它具有选项、参数、子命令、数据验证等功能。
通常,Typer 往往是程序的入口点,从用户那里获取第一个输入。
Rich 对于需要显示信息的部件很有用。在屏幕上显示漂亮的内容。
将 Typer 和 Rich 相结合,可以为您的命令行应用程序实现最佳效果。
“标准输出”和“标准错误”¶
打印工作的底层方式是操作系统(Linux、Windows、macOS)将我们打印的内容视为我们的 CLI 程序正在向一个名为“标准输出”的“虚拟文件”写入文本。
当我们的代码“打印”内容时,它实际上是“写入”到“标准输出”的这个“虚拟文件”中。
这可能看起来很奇怪,但这就是 CLI 程序和操作系统相互交互的方式。
然后操作系统在屏幕上显示我们的 CLI 程序“写入”到名为“标准输出”的“虚拟文件”中的任何内容。
标准错误¶
还有一个名为“标准错误”的“虚拟文件”,通常仅用于错误。
但我们也可以“打印”到“标准错误”。这两个都会在终端上显示给用户。
信息
如果您使用 PowerShell,您打印到“标准错误”的内容很可能不会显示在终端中。
在 PowerShell 中,要查看“标准错误”,您必须检查变量 $Error
。
但在 Bash、Zsh 和 Fish 中,它会正常工作。
打印到“标准错误”¶
您可以通过使用 stderr=True
创建一个 Rich Console
来打印到“标准错误”。
提示
stderr
是“标准错误”的缩写。
使用 stderr=True
告诉Rich,输出应显示在“标准错误”中。
import typer
from rich.console import Console
err_console = Console(stderr=True)
def main():
err_console.print("Here is something written to standard error")
if __name__ == "__main__":
typer.run(main)
当您在终端中尝试它时,它可能看起来完全一样
$ python main.py
Here is something written to standard error
“标准输入”¶
最后,当您在键盘中键入文本到终端时,操作系统也会将其视为另一个“虚拟文件”,您正在向其写入文本。
此虚拟文件称为“标准输入”。
这有什么用¶
现在这可能看起来毫无用处 🤷♂。
但理解这一点在未来会派上用场,例如用于自动完成和测试。
Typer Echo¶
Typer 还具有一个小实用程序 typer.echo()
,用于在屏幕上打印信息,它直接来自 Click。但通常您不需要它。
对于最简单的情况,您可以使用标准 Python print()
。
对于您希望以更美观或更高级的内容显示数据的情况,您应该使用 Rich。
为什么是 typer.echo
¶
typer.echo()
(实际上只是 click.echo()
)应用一些检查来尝试将二进制数据转换为字符串,以及其他类似操作。
但在大多数情况下,您不需要它,因为在现代 Python 字符串(str
)中已经支持并使用 Unicode,并且您很少会处理您想要在屏幕上打印的纯 bytes
。
如果您有一些 bytes
对象,您可能希望在尝试打印它们之前有意直接解码它们。
如果您想使用颜色和其他功能打印数据,那么您最好使用 Rich 中更高级的工具。
信息
typer.echo()
直接来自 Click,您可以在 Click 文档 中阅读更多相关信息。
颜色¶
技术细节
颜色在终端中工作的原理是使用一些代码(ANSI 转义序列)作为文本的一部分。
因此,有色文本仍然只是一个 str
。
提示
同样,您最好使用 Rich 来实现此目的。😎
您可以使用 typer.style()
创建有色字符串以输出到终端,它会为您提供 str
,然后您可以将其传递给 typer.echo()
import typer
def main(good: bool = True):
message_start = "everything is "
if good:
ending = typer.style("good", fg=typer.colors.GREEN, bold=True)
else:
ending = typer.style("bad", fg=typer.colors.WHITE, bg=typer.colors.RED)
message = message_start + ending
typer.echo(message)
if __name__ == "__main__":
typer.run(main)
提示
参数 fg
和 bg
接收带有颜色名称的字符串,用于“foreground”和“background”颜色。您可以简单地传递 fg="green"
和 bg="red"
。
但是 Typer 将它们全部作为变量提供,例如 typer.colors.GREEN
,这样您就可以在选择它们时使用自动完成。
检查一下
您可以将这些函数参数传递给 typer.style()
fg
:前景色。bg
:背景色。bold
:启用或禁用粗体模式。dim
:启用或禁用暗淡模式。此模式支持不佳。underline
:启用或禁用下划线。blink
:启用或禁用闪烁。reverse
:启用或禁用反向渲染(前景色变为背景色,反之亦然)。reset
:默认情况下,在字符串的末尾添加一个重置所有代码,这意味着样式不会继承。可以禁用此功能以组合样式。
信息
您可以在 Click 关于 style()
的文档 中阅读更多相关信息。
typer.secho()
- 样式和打印¶
提示
如果您没有看到上面,您最好使用 Rich 来实现此目的。😎
有一个更短的格式可以同时使用 typer.secho()
进行样式和打印,它类似于 typer.echo()
,但还添加了类似于 typer.style()
的样式
import typer
def main(name: str):
typer.secho(f"Welcome here {name}", fg=typer.colors.MAGENTA)
if __name__ == "__main__":
typer.run(main)
检查一下