いつもプロトタイピングをするときに、CLIのツールに仕立てることがあります。本業の機械系設計事務所で効率化を確認するツールをとりあえず用意したい時、自動化タスクの動作を確認したい時に、CLIツールを作って試せると便利です。
その時にユーザーからの対話質問を受けたい時があります。たとえば管理番号や顧客名、案件のおおざっぱな種類などを入力したくなります。
そのときはコマンドの引数を使う(Python標準ライブラリのargparseやサードパーティのclick)のが一般的ですが、質問形式で対話的に入力を受け付けるツールを作ると、引数を忘れても大丈夫です。本格的なCLIコマンドとして使うなら引数用意も大事ですが、あくまでお試しでコマンドを用意したい、と思うときに便利と思ってます。
Pythonで対話入力を受け付けるツールを作るときには、Questionaryを使うと良い、というお話です。
Questionaryの紹介
実は前に紹介したcopierで利用されているライブラリです。この入力方法使ってみたいと思って調べてましたw
特徴は「✨ Questionary is a Python library for effortlessly building pretty command line interfaces ✨」(公式サイトより)だそうで綺麗なCLIが簡単に作れるということです。実際にこんな風にわかりやすくなります。
日本語表示も入力も今のところ問題なさそうです。
使い方
インストールはpipでサクッと入ります。
pip install questionary
対話のサンプル
使い方ですがシンプルです。
公式サイトでもGIF動画になっていますが、日本語入力も問題なく動作します。
import questionary
your_name = questionary.text("あなたの名前を教えてください").ask()
print(f"こんにちは、{your_name}さん")
questionary.[質問のタイプ]
で質問のオブジェクトを作り、ask()
メソッドで質問を実行します。答えは戻り値として受け取っています。
コード上に質問を差し込むだけで、非常にシンプルなのですが対話的なツールを作ることができます。
質問の種類
最初の例はquestionary.text
でしたが、他にも色々な質問の種類があります。
公式サイトの質問の種類によると
- use Text to ask for free text input
- use Password to ask for free text where the text is hidden
- use File Path to ask for a file or directory path with autocompletion
- use Confirmation to ask a yes or no question
- use Select to ask the user to select one item from a beautiful list
- use Raw Select to ask the user to select one item from a list
- use Checkbox to ask the user to select any number of items from a list
- use Autocomplete to ask for free text with autocomplete help
- use Press Any Key To Continue to ask the user to press any key to continue
などたくさんあります。とくにSelectとCheckboxは便利で良く使ってます。
Selectはquestionary.select
になります。名前の通り複数の項目を選択できます。
import questionary
eat_newyear = questionary.select(
"お正月に食べたものは?", choices=["おせち", "お雑煮", "カレー", "日本酒"]
).ask()
print(f"あなたが食べたり飲んだりしたのは、{eat_newyear}ですね!いいお正月でしたね!")
Checkboxはquestionary.checkbox
で作成します。
import questionary
dream_newyear = questionary.checkbox(
"お正月に見た夢は?", choices=["富士山🗻", "タカ🦅", "茄子🍆"]
).ask()
print(f"あなたが見た夢は、{dream_newyear}ですね!最高の初夢でしたね!")
Tips
質問中にキャンセルする
Questionaryのキャンセルの対応方法はsafeとunsafeという概念があり、ここではsafeの方を使っています。
たとえばは間にキャンセルするとき、キーボードのctrl+cでKeyboardInterruptが発生させると、直前の質問はNoneを返すようになってます。戻り値の内容でキャンセルされたかどうかを判断できます。
もちろんキャンセルでコマンド自体を終了する場合はsys.exit
などで明示的に終わりにします。
import questionary
your_name = questionary.text("あなたの名前を教えてください").ask()
if your_name is None:
print("キャンセルされました")
sys.exit(1)
質問を飛ばしたり分岐させる
分岐をする時には、条件分岐を使います。
たとえば、ある質問Aに対しての補足質問Bをするときに、Aの答えによってBを飛ばしたりできます。
import questionary
# questonary.confirm()でyes/noの質問をする
bougth_omikuji = questionary.confirm("おみくじを引きましたか?").ask()
# おみくじを引いた場合のみ質問する
omikuji_result = (
questionary.select(
"おみくじの結果はどうでしたか?",
choices=[
"大吉",
"中吉",
"小吉",
"吉",
"末吉",
"凶",
"大凶",
],
)
.skip_if(
bougth_omikuji is False, default=False
) # おみくじを引いていない場合をis演算子で判定
.ask()
)
if omikuji_result:
print(f"おみくじの結果は{omikuji_result}でした")
else:
print("おみくじを引いていないので結果はわかりません")
デフォルトの選択肢を設定する
questionary.select
やquestionary.checkbox
ではデフォルトの選択肢を設定できます。
たとえば特定の設定をしたいときにデフォルト状態を設定しておくときに便利です。
選択肢のchoice引数に渡すリストにquestionary.Choice
のオブジェクトを使って選択肢を作ると設定できます。
import questionary
from questionary import Choice
## 年末年始の掃除リストを作る。ゴミ出しは必須
souzi_list = [
Choice("ゴミ出し", checked=True),
Choice("床の掃除"),
Choice("窓の掃除"),
Choice("ガスコンロの掃除"),
Choice("換気扇の掃除"),
Choice("冷蔵庫の掃除"),
Choice("洗濯機の掃除"),
Choice("エアコンの掃除"),
Choice("照明器具の掃除"),
Choice("トイレの掃除"),
Choice("風呂の掃除"),
]
choiced_souzi_list = questionary.checkbox(
"掃除リストを作ります。", choices=souzi_list
).ask()
print("今年中に掃除をしたいToDoリストです!")
for heya in choiced_souzi_list:
print(f"- [ ] {heya}")
そのほか、プロンプトのグラフィカルな設定も可能です。デフォルトでほぼ問題ないと思いますが、もし気になる方は公式サイトの解説も見てみてください。
- 参考: Themes & Styling
まとめ
PythonでユーザーフレンドリーなCLIツールを作る時には、Questionaryを使うと良いというお話でした。
ちょっとしたツールを作るときに通常のコマンド引数より簡易に対話インターフェイスを作ることができます。オススメです。
参考
- 公式のサンプル
- Pythonで対話式CLIツールを作る #Python - Qiita
- この記事のサンプルコード: https://github.com/hrsano645/exam-questionary
宣伝
弊社の宣伝です! 自動車プレス金型の機械設計を行う設計事務所で、製品や試作品の3Dモデリングのお仕事も受け付けています。
また製造業で上記記事で扱う作業の自動化やその先に繋がるデジタル化、DXに取り組みたい方もご相談承っております。
ぜひお気軽にお問い合わせください!
- お問い合わせは設計事務所のWEBサイトにて!