印刷と色
通常の`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`は「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¶
**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`のような変数として提供しているので、選択中に自動補完を使用できます。
確認してください
これらの関数引数を 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)
確認してください