Pythonにはinputという組み込み関数がある。これは、ユーザからの入力を受け付ける関数である。

user_input = input("入力してください: ")

以上を実行すると、ターミナルに入力してください: と表示され、入力待ちの状態になる。 そして、Enterを押すとそれまでに入力した内容が確定され、user_inputに格納される。 簡易的な入力処理を実装する上で、便利な関数である。

しかしこのinput関数であるが、簡易的な処理だけあって、かなり機能は貧弱なものとなっている。 例えば、矢印キーが効かない。”abcde”と入力し、Enterを押す前に最初の文字”a”を”z”に修正しようとして左矢印キーを押すと、 カーソルが左に動くのではなく、^[[Dという入力がなされる。

また、これは環境に依存するようだが、日本語を入力するとバックスペースによる文字の削除がうまくできないという問題も起こる。 筆者の環境では、日本語(全角文字)を入力した直後にバックスペースを押すと、入力した文字が削除されるとともに、 「全角ではなく半角の分だけ」カーソルが戻る、という現象が起こった。調査の結果、この現象はmacOSで起こりやすいようだ。

これらの問題を解決する一番簡単な方法は、import readlineinput関数の前に挿入することである。

import readline
user_input = input("入力してください: ")

これだけで、上で挙げた問題点は全て解消する。input関数がreadlineの機能を使ったものに置き換わるためだ。

readlineモジュールを用いた方法は、既存のコードにおいてinputを呼び出している部分に一切手を加える必要がないことが、大きな利点である。 欠点は、import readlineが見かけ上「インポートしたのに使われていないモジュール」となってしまうため、 Linterが警告を出す場合があることくらいだろうか。

もう一つの選択肢として、prompt-toolkitという外部パッケージを使うという方法もある。 このパッケージ内のpromptという関数は、このinput関数の高機能版といった位置付けのものである。

from prompt_toolkit import prompt
user_input = prompt("入力してください: ")

これもまた、上で示したinputの例と同じような挙動となる。 prompt関数の方は色々なオプションを指定することができて、たとえば複数行の入力を受け付けるなどといった機能がある。 かなり機能豊富であるが、inputとは違い「キーボードからの入力」に特化しており、 「リダイレクトされているかもしれない標準入力」からの入力は想定していないと思われる。 実際、標準入力がリダイレクトされているとWarning: Input is not a terminal (fd=0)という警告を発する。