終了する¶
ある時点でコマンドを終了し、それ以降の実行をすべて止めたい場面があります。
コードがプログラムの正常終了を判断した場合もあれば、処理が中断された場合もあるでしょう。
CLI プログラムを Exit する¶
通常は CLI プログラムのコードを最後まで実行させれば十分ですが、シナリオによっては途中で終了したくなることがあります。そして、それ以降のコードが実行されないようにしたい場合もあります。
これは、必ずしもエラーを意味するわけではありません。単に、それ以上実行する必要がないだけです。
その場合は、typer.Exit() 例外を raise できます。
import typer
existing_usernames = ["rick", "morty"]
def maybe_create_user(username: str):
if username in existing_usernames:
print("The user already exists")
raise typer.Exit()
else:
print(f"User created: {username}")
def send_new_user_notification(username: str):
# Somehow send a notification here for the new user, maybe an email
print(f"Notification sent for new user: {username}")
app = typer.Typer()
@app.command()
def main(username: str):
maybe_create_user(username=username)
send_new_user_notification(username=username)
if __name__ == "__main__":
app()
この例では、いくつか注目すべき点があります。
- CLI プログラムは他の関数ではなく
main()関数です。CLI 引数 を受け取るのはこれです。 maybe_create_user()関数は、typer.Exit()を raise することでプログラムを終了できます。maybe_create_user()によってプログラムが終了した場合、main()内のsend_new_user_notification()は決して実行されません。
確認してみましょう。
$ python main.py Camila
User created: Camila
Notification sent for new user: Camila
// 既存 user で試します
$ python main.py rick
The user already exists
// 通知用のコードは実行されず、2 つ目のメッセージは表示されないことに注目してください
Tip
例外を raise していても、それが必ずしもエラーを意味するわけではありません。
これは "error" のように機能して、すべての実行を止められるため例外で実現されています。
ただしその後 Typer がそれを catch し、プログラムを通常どおり終了させます。
エラー付きで終了する¶
typer.Exit() は、省略可能な code parameter を受け取ります。デフォルトでは code は 0 で、エラーがなかったことを意味します。
0 以外の数値を code として渡すと、プログラムの実行中にエラーがあったことをターミナルに伝えられます。
import typer
app = typer.Typer()
@app.command()
def main(username: str):
if username == "root":
print("The root user is reserved")
raise typer.Exit(code=1)
print(f"New user created: {username}")
if __name__ == "__main__":
app()
確認してみましょう。
$ python main.py Camila
New user created: Camila
// 最後に実行したプログラムの終了コードを表示します
$ echo $?
0
// 今度はエラー付きで終了させます
$ python main.py root
The root user is reserved
// 最後に実行したプログラムの終了コードを表示します
$ echo $?
1
// 1 はエラーあり、0 はエラーなしを意味します。
Tip
このエラーコードは、あなたの CLI プログラムを実行する別のプログラム(たとえば Bash script)から使われることがあります。
Abort¶
プログラムを "abort" するために使える特別な例外があります。
これは typer.Exit() とほぼ同じように動作しますが、画面に "Aborted!" を表示します。実行が中断されたことを明示したい場合に、あとで役立つことがあります。
import typer
app = typer.Typer()
@app.command()
def main(username: str):
if username == "root":
print("The root user is reserved")
raise typer.Abort()
print(f"New user created: {username}")
if __name__ == "__main__":
app()
確認してみましょう。
$ python main.py Camila
New user created: Camila
// 今度はエラー付きで終了させます
$ python main.py root
The root user is reserved
Aborted!