コンテンツにスキップ

印刷と色

通常の`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">&apos;name&apos;</font>: <font color="#A6E22E">&apos;Rick&apos;</font>,
    <font color="#A6E22E">&apos;age&apos;</font>: <font color="#A1EFE4"><b>42</b></font>,
    <font color="#A6E22E">&apos;items&apos;</font>: <b>[</b>
        <b>{</b><font color="#A6E22E">&apos;name&apos;</font>: <font color="#A6E22E">&apos;Portal Gun&apos;</font><b>}</b>,
        <b>{</b><font color="#A6E22E">&apos;name&apos;</font>: <font color="#A6E22E">&apos;Plumbus&apos;</font><b>}</b>
    <b>]</b>,
    <font color="#A6E22E">&apos;active&apos;</font>: <font color="#A6E22E"><i>True</i></font>,
    <font color="#A6E22E">&apos;affiliation&apos;</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`は「standard error」の略です。

`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

警告

ほとんどの場合、高度な情報を表示するには、Richを使用することをお勧めします。

おそらくこのセクションの残りはスキップできます。🎉😎

**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`です。

ヒント

繰り返しますが、 hierfür Richを使用する方がはるかに優れています。😎

`typer.style()`を使用して、ターミナルに出力する色付きの文字列を作成できます。これにより、`typer.echo()`に渡すことができる`str`が得られます。

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`は、「**前景色**」と「**背景色**」の色名を持つ文字列を受け取ります。単に`fg="green"`と`bg="red"`を渡すこともできます。

しかし、**Typer**はそれらすべてを`typer.colors.GREEN`のような変数として提供しているので、選択中に自動補完を使用できます。

確認してください

python main.py すべて順調です python main.py --no-good すべて不良です

これらの関数引数を 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)

確認してください

python main.py Camila ようこそ、Camila さん