見出し画像

pythonプログラム 初歩の初歩9/複数行入力


こんにちは、makokonです。
今日は簡単な小技です。

いつもチャットしていますか。
makokonは、目的別にしょっちゅうチャットアプリを書くのですが、コンソールチャットアプリを結構多用しています。圧倒的に簡単にかけて、周辺の部品モジュールテストがし易いですから。
そんなとき、多少不便なのが、複数行の入力を一度にすることができない問題です。python標準のinput()では、改行を入力の終了とするので仕方ないのですが、困ることは困ります。


事例

こんにちは
私はmakokonです。
あなたは誰ですか。

入力用テキスト

つまり、こんな入力を以下のコード実行して、入力部でコピーします。


while True:
    text = input("何か話してください : ")
    if text=="exit":
        print("会話を終了します")
        break
    print("AIの応答です")
    print(text)

> python minput.py
何か話してください : こんにちは
AIの応答です: こんにちは
何か話してください : 私はmakokonです。
AIの応答です: 私はmakokonです。
何か話してください : あなたは誰ですか。
AIの応答です: あなたは誰ですか。
何か話してください :

実行結果

これは、すこぶる具合が悪い。もちろんWEBアプリを作るときはtextboxの情報は改行付きテキストのコピーでは確定せずに、実際に改行キーを入力したときに確定とか、確定しても自動的に処理が進まずに”送信”ボタンを用意したり、対策は簡単なのですが、コンソールでは対応できません。

対策

しょうがないから、input()のかわりにread_multiline_input()関数を作ることにしました。

def read_multiline_input(prompt="Input (Ctrl+D to end): "):
    print(prompt, end="")
    lines = []
    try:
        while True:
            line = input()
            lines.append(line)
    except EOFError:
        pass
    return "\n".join(lines)
    
# 使用例
while True:
    print("何か話してください。")
    text = read_multiline_input()
    if text=="exit":
        print("会話を終了します")
        break
    print(f"AIの応答です: {text}")



>python minput.py
何か話してください。
Input (Ctrl+D to end): こんにちは
私はmakokonです。
あなたは誰ですか。
^Z
AIの応答です: こんにちは
私はmakokonです。
あなたは誰ですか。
何か話してください。
Input (Ctrl+D to end): こんにちは
私はmakokonです。
あなたは誰ですか。
^Z
AIの応答です: こんにちは
私はmakokonです。
あなたは誰ですか。
何か話してください。
Input (Ctrl+D to end): exit
^Z
会話を終了します

実行結果

こんな感じです。3行の入力が一回で入っています。
なお、今回はwindowsのターミナルを使っているので最後の入力は、^Z(Ctrl+Z)になっています。UNIX系ならCtrl+Dが多いでしょう。(システムの設定しているEOF(End of File)を入力してください。

モジュール化

せっかく作ったread_multiline_input()ですが、これをいちいちプログラムを作成するたびに、コピーするのも面倒な話です。
便利に利用するためにモジュール化します。
とは言ってもやり方は簡単で、

ステップ1: read_multiline_input()を含むモジュールを作成

最初に、read_multiline_input()関数を含むPythonファイル(例: multiline_input.py)を作成します。

# multiline_input.py

def read_multiline_input(prompt="Input (Ctrl+D to end): "):
    print(prompt, end="")
    lines = []
    try:
        while True:
            line = input()
            lines.append(line)
    except EOFError:
        pass
    return "\n".join(lines)

ステップ2: 作成したモジュールを他のスクリプトからインポート

次に、multiline_input.pyモジュールを他のPythonスクリプトからインポートして、read_multiline_input()関数を使用します。

# main_script.py

from multiline_input import read_multiline_input

def main():
    text = read_multiline_input("カスタムプロンプト: ")
    print("入力されたテキスト:")
    print(text)

if __name__ == "__main__":
    main()

モジュール化により、read_multiline_input()関数を他のプロジェクトでも簡単に使えるようになり、コードの保守性や拡張性が向上します。ただし、read_multiline_input()を使用するスクリプトがmultiline_input.pyと同じディレクトリにあるか、またはmultiline_input.pyがPythonのモジュール検索パスに含まれていることを確認する必要があります。

なお、いちいちmultiline_input.pyを、同じディレクトリにコピーするのでは、面倒くささの点で本末転倒なので、環境変数 PYTHONPATH を使って、Pythonのモジュール検索パスにディレクトリを追加することができます。この方法はOSに依存しますが、ユーザーが自由に設定できるため、自作のモジュールを置くパスとして利用することができます。

  • Linux/macOS:

    1. export PYTHONPATH="${PYTHONPATH}:/your/custom/path"

  • Windows (コマンドプロンプト):

    1. set PYTHONPATH=%PYTHONPATH%;C:\your\custom\path

この設定は、シェルセッションやコマンドプロンプトのセッションに対して一時的に適用されます。恒久的に設定するには、OSの設定で環境変数を永続化する必要があります。(時々作って、便利な関数はこの場所において使っています form mymodule.py import myfunctionみたいにして色々集めている)

まとめ

今日は小技ながら、汎用性の高い複数行入力インプット関数を作りました。
pythonの標準関数にないものでも、ちょっとした工夫で汎用的な関数を作ることができます。
また、作った関数はモジュール化して、必要なプログラムでimportする事によって、通常の関数と同様に利用することができます。
専門性が高く、アップデートの可能性が高い関数は、管理しにくくなるので、使用スクリプト中で管理したほうが安全かもしれませんが、汎用的な関数は,まとめて使えるようにしておくと便利ですよ。

おまけ タイトル画の説明 by GPT-4-vision

この画像には、コンピューターのデュアルモニターの前で作業している若い男性が描かれています。彼は集中してキーボードに手を置き、画面に表示されているコーディング作業に注意を払っています。机の上には開かれた本、筆記用具が入ったカップ、携帯電話が置かれており、周囲には多くの本が積み重ねられ、書棚に整理されています。机の上にはまた、植物が入ったマグカップもあります。画像は静かながら活発な学習または作業環境を表しており、Pythonのロゴが3つ表示されていることから、男性がPythonプログラミングに携わっていることが示唆されています。


この記事が気に入ったらサポートをしてみませんか?