【第7回】while文入門:入力が終わるまでログを取り続ける小さなツール

Python入門

第6回までで、

  • コーヒーや釣りのログを リスト+辞書 で扱い
  • if文とfor文で 条件に合うログだけを抽出
  • CSVファイルとして 外の世界に保存 する

というところまで進んできました。

ただ、実際の生活に寄せて考えると、こんな欲が出てきます。

  • コーヒーを飲んだタイミングで、さっと1件入力したい
  • 釣りのあと、その日の釣果をまとめて入力したい
  • 「もういいかな」と思うところまで、何件でも入れられるようにしたい

そこで今回のテーマは、

「入力が終わるまで、ログを取り続ける小さなツール」を while 文で作ること。

キーワードは while文input()、そして break

湖のほとりでも、自宅のデスクでも、

  • スクリプトを起動する
  • コーヒーや釣りの情報をちょこちょこ入力する
  • q を打つと終わって、CSVに保存される

そんな小さな “celestial biome ロガー” を目指していきます。


この回のゴールと全体像

第7回でできるようになってほしいことは、次の4つです。

  1. while文の基本形と「条件がTrueのあいだ繰り返す」というイメージが持てる
  2. 無限ループ+break というよくあるパターンを理解できる
  3. input() と while 文を組み合わせて、対話的にログを入力できる
  4. 入力された複数のログをCSVファイルにまとめて保存できる

ここまで来れば、

  • 「自分がやめると決めるまで続くループ」

を扱えるようになります。

while文とは?「〜であるあいだずっと続ける」

while文は、

ある条件がTrueであるあいだ、処理をくり返す構文

です。

基本形はこうです。

while 条件:
    繰り返したい処理
  • 条件True のあいだは、何度でも繰り返される
  • 条件False になったタイミングで、while ループを抜ける

という動きになります。

シンプルな例:3回だけループする

count = 0

while count < 3:
    print("count は", count, "です")
    count = count + 1  # ここを忘れると無限ループ!

print("ループが終わりました")

実行結果のイメージ:

count は 0 です
count は 1 です
count は 2 です
ループが終わりました
  • 最初は count = 0
  • count < 3 → True なので中の処理を実行
  • 最後に count = count + 1 で count が 1, 2, 3… と増えていく
  • count が 3 になったとき count < 3 が False になり、ループ終了

よくあるミス は、count = count + 1 を書き忘れて、条件が永遠に変わらないこと。
そうなると、処理が終わらなくなります(無限ループ)。

あえて「無限ループ」にして、breakで抜ける書き方

さきほどは「回数」で終わりを決めましたが、
今回作りたいツールは、

  • 「自分が q と入力したら終わる」

という、回数が決まっていないくり返し です。

こういうときによく使うパターンが、

while True:
    何かする

    if 終了条件:
        break

という形です。

  • while True: は、条件が常に True なので、理論上は永遠にループする
  • ただし、ある条件になったら break でループを抜ける

という「意図的な無限ループ」です。

q が入力されたら終わる簡単な例

while True:
    text = input("何か入力してください(qで終了):")

    if text == "q":
        print("終了します。")
        break

    print("あなたが入力したのは:", text)

input() は、ユーザーから1行文字列を入力してもらう関数です。

  • ユーザーが q と入力したら break でループ終了
  • それ以外なら、その文字を表示してループを続ける

という流れになっています。

コーヒーログを while+input で取り続ける

では、いよいよ本題。
「入力が終わるまでコーヒーログを取り続ける小さなツール」 を作ります。

流れとしてはこんな感じです。

  1. ループの外で「空のリスト」を用意
  2. while True で、1杯分の情報を入力してもらう
  3. q が入力されたら break で終了
  4. 入力されたログを、ループの外でCSVにまとめて書き出す

まずはログを集める部分から

# coffee_input.py

coffee_logs = []  # 入力されたログを貯めるリスト

while True:
    name = input("コーヒー名を入力してください(終了するには q):")
    if name == "q":
        print("入力を終了します。")
        break

    roast = input("焙煎度(浅煎り・中煎り・深煎りなど):")
    memo = input("ひとことメモ:")
    score_str = input("スコア(0〜5の数字):")

    # 入力されたスコアをfloatに変換(失敗したら3.0にするなどの簡易処理)
    # 例外処理について以下の補足で解説します。
    try:
        score = float(score_str)
    except ValueError:
        print("数値に変換できなかったので、スコアを 3.0 にします。")
        score = 3.0

    log = {
        "name": name,
        "roast": roast,
        "memo": memo,
        "score": score
    }

    coffee_logs.append(log)
    print("1件ログを追加しました。")
    print("----------------------")

print("入力された件数:", len(coffee_logs))

ここではまだ CSVには書き込んでいません
とりあえず while で、複数件のログをリストにためるところまでです。

ポイント:

  • coffee_logs = [] はループの外(最初)で1回だけ作る
  • while の中で1件分の辞書 log を作り、それを append() で追加
  • q を入力したときだけ break で抜ける

まずはここまでを動かして、len(coffee_logs) が 0,1,2,… と増えることを確認してみてください。

補足:try / except は「エラーが出ても落とさないためのクッション」

第7回のコードの中で、初めて

try:
    score = float(score_str)
except ValueError:
    print("数値に変換できなかったので、スコアを 3.0 にします。")
    score = 3.0

という書き方が出てきました。
これは 「try / except(トライ・エクセプト)」 と呼ばれる構文です。

ざっくりイメージだけ先に持っておくと:

  • try:
    • 「ここでエラーが出るかもしれないけど、とりあえずやってみる場所」
  • except エラーの種類:
    • 「もしそのエラーが起きたら、代わりにここを実行してね」

という クッション のようなものです。

例えば、スコア入力が数値じゃなかったら?

普通にこう書くとします。

score = float(score_str)

score_str"4.5" みたいな 数字っぽい文字列 なら大丈夫ですが、

  • 「美味しい」とか
  • 空文字(何も入っていない)

が入っていると、Python は

「数値に変換できないよ!」

と怒って エラーを出して、その時点でプログラムを止めてしまいます。

そこで、

try:
    score = float(score_str)
except ValueError:
    print("数値に変換できなかったので、スコアを 3.0 にします。")
    score = 3.0

と書いておくと、

  • まず try: の中で float(score_str) を試す
  • もし ValueError(「変換できない」という種類のエラー)が起きたら
    • except ValueError: の中に進んで
    • エラーメッセージを出しつつ、score = 3.0 として処理を続ける

という動きになります。

つまり、

try / except は「エラーが出ても、プログラムを落とさず、ソフトランディングさせるための仕組み」

くらいのイメージでOKです。

本格的な解説はもう少し後の回で扱う予定なので、
今のところは

「入力が変でも落ちないようにする、おまじない」

くらいで気軽に使ってみてください。


集めたログをCSVに保存する

次に、入力が終わったあとで、
集めたログを CSV に書き出してみます。

今回は、

  • すでに coffee_logs.csv があればヘッダーなしで追記
  • なければヘッダー付きで新規作成

という形にしてみます。

# coffee_input.py

import csv
import os

coffee_logs = []

while True:
    name = input("コーヒー名を入力してください(終了するには q):")
    if name == "q":
        print("入力を終了します。")
        break

    roast = input("焙煎度(浅煎り・中煎り・深煎りなど):")
    memo = input("ひとことメモ:")
    score_str = input("スコア(0〜5の数字):")

    try:
        score = float(score_str)
    except ValueError:
        print("数値に変換できなかったので、スコアを 3.0 にします。")
        score = 3.0

    log = {
        "name": name,
        "roast": roast,
        "memo": memo,
        "score": score
    }

    coffee_logs.append(log)
    print("1件ログを追加しました。")
    print("----------------------")

print("入力された件数:", len(coffee_logs))

if coffee_logs:
    filename = "coffee_logs.csv"
    fieldnames = ["name", "roast", "memo", "score"]

    file_exists = os.path.exists(filename)

    with open(filename, "a", newline="", encoding="utf-8") as f:
        writer = csv.DictWriter(f, fieldnames=fieldnames)

        # ファイルがまだなければヘッダーを書く
        if not file_exists:
            writer.writeheader()

        writer.writerows(coffee_logs)

    print(f"{filename} に {len(coffee_logs)} 件のログを書き込みました。")
else:
    print("ログが1件も入力されなかったので、ファイルには書き込みませんでした。")

これで、

  • スクリプトを起動
  • 満足するまでコーヒーの情報を入力
  • q で終了
  • すべてのログが coffee_logs.csv に追記される

という流れができました。

朝・昼・夜で何度起動しても、同じ coffee_logs.csv にログが積み上がっていきます。

釣りログ版に応用する

同じパターンで、釣りログ版も作れます。
ここでは少し項目を絞ったシンプルな例を載せておきます。

# fishing_input.py

import csv
import os

fishing_logs = []

while True:
    date = input("日付を入力してください(例:2025/05/01、終了するには q):")
    if date == "q":
        print("入力を終了します。")
        break

    lake = input("場所(湖の名前など):")
    fish_type = input("魚種(ブラウン・レイクなど):")
    length_str = input("サイズ(cm):")
    is_released_str = input("リリースしましたか?(y/n):")

    try:
        length = int(length_str)
    except ValueError:
        print("整数に変換できなかったので、サイズを 0cm とします。")
        length = 0

    is_released = (is_released_str.lower() == "y")

    log = {
        "date": date,
        "lake": lake,
        "fish_type": fish_type,
        "fish_length_cm": length,
        "is_released": is_released
    }

    fishing_logs.append(log)
    print("1件ログを追加しました。")
    print("----------------------")

print("入力された件数:", len(fishing_logs))

if fishing_logs:
    filename = "fishing_logs.csv"
    fieldnames = ["date", "lake", "fish_type", "fish_length_cm", "is_released"]

    file_exists = os.path.exists(filename)

    with open(filename, "a", newline="", encoding="utf-8") as f:
        writer = csv.DictWriter(f, fieldnames=fieldnames)

        if not file_exists:
            writer.writeheader()

        writer.writerows(fishing_logs)

    print(f"{filename} に {len(fishing_logs)} 件のログを書き込みました。")
else:
    print("ログが1件も入力されなかったので、ファイルには書き込みませんでした。")

これで、釣りから帰ってきた夜に

  • python fishing_input.py を起動
  • その日の釣果を思い出しながら何件か入力
  • 入力し終わったら q

というように、儀式のようなログタイム を持てます。

よくあるつまずきポイント(while+input 編)

無限ループから抜けられない

  • while True: を使うときは、必ず break の条件を書いておく
  • 条件が絶対に到達するか、コードをよく見直す

入力結果の型(文字列・数値)を混同する

  • input() で受け取った値は 必ず文字列
  • 数値として使いたい場合は int()float() で変換する
  • 変換に失敗する可能性も考えて try / except を使うと安全

リストの初期化位置を間違える

  • coffee_logs = []fishing_logs = []while の前 で1回だけ行う
  • while の中で毎回 [] を作り直してしまうと、ログが1件ずつしか残らない

今日のまとめ while文で「終わりを自分で決める」ループを持つ

今回は、

  • while文の基本形(条件がTrueのあいだくり返す)
  • 無限ループ+break というよく使うパターン
  • input() と while を組み合わせた対話的なログ入力
  • 集めたログをCSVにまとめて保存する流れ

までを見てきました。

これで、

  • 「何回くり返すか決まっていない処理」

を、自分のタイミングで終わらせられるようになりました。

朝のコーヒー、昼の一杯、夜の一杯。
春の中禅寺湖、夏のブラウン、秋のレイク。

それぞれの「小さな瞬間」を、
while文を使って少しずつCSVに積み上げていけます。

次回予告 関数で「よく使う処理」に名前をつけて整理する

ここまでコードを書いてくると、こんな感覚も出てきます。

  • 「CSVに書き込む処理、毎回ほとんど同じことを書いてない?」
  • 「ログ1件分を辞書にまとめるところも、パターンが似ているな」

この 「似たような処理をまとめたい」 という感覚は、とても大事です。

次回は、

  • def を使って 関数 を定義し
  • 「コーヒーログを書き込む関数」
  • 「釣りログを書き込む関数」

のように、よく使う処理に名前をつけて整理していきます。

関数を使えるようになると、

  • コードの重複が減って読みやすくなる
  • 「何をしているのか」が名前から分かる
  • 将来クラスや大きなアプリを作るときの土台になる

というメリットがあります。

というわけで次回は、

第8回:関数入門 ログ処理に名前をつけてスッキリさせる

を予定しています。
コーヒーと湖のログツールを、そのまま題材に進めていきましょう。

コメント