Python | 1 日 90 分 × 7 日アプリ学習:ファイルを読み込むアプリ(初級編)

Web APP Python
スポンサーリンク

6日目のゴール

6日目のテーマは
「ファイルを“読みっぱなし”ではなく、“読み方をコントロールできるようになること” です。

ここまでであなたは、

ファイル全体を読む
1行ずつ読む
先頭・末尾だけ読む
キーワードで検索する
行の一部だけを抜き出す

というところまで来ています。

6日目ではここから一歩進んで、

読み込んだ行を「一度ためてから」いろいろな表示に使い回す
ページごと(何行ずつ)に分けて表示する
「read は一度だけ、表示は何度でも」という発想を身につける

ここを目指します。


読み込みと表示を“分けて考える”

今までは「読みながら表示」していた

これまでのコードは、だいたいこうでした。

with open(filename, "r", encoding="utf-8") as f:
    for line in f:
        print(line.strip())
Python

これは、

読み込む
すぐ表示する

をセットでやっています。

これはシンプルで分かりやすい一方で、

「同じファイルを、別の表示方法でもう一度見たい」
「ページごとに分けて表示したい」

といったときに、
毎回ファイルを開き直す必要が出てきます。

そこで今日は、

一度だけ全部読み込む
その結果(行のリスト)を、いろんな表示に使い回す

という形にしていきます。


行のリストとして読み込む関数を作る

readlines で「全部の行」を一度に取る

まずは、
「ファイルを読み込んで、行のリストとして返す」
という共通関数を作ります。

def load_lines(filename):
    with open(filename, "r", encoding="utf-8") as f:
        lines = f.readlines()
    return lines
Python

この関数は、日本語で言うとこうです。

「指定されたファイルを読み込みモードで開き、
全ての行をリストとして読み込んで返す。」

ここでの重要ポイントは、

ファイルを開くのはこの関数だけ
あとは「行のリスト」を相手にすればよい

という構造にしていることです。


行のリストを「そのまま表示」する関数

読み込みと表示を完全に分離する

さっきの load_lines を使って、
「全部表示する」関数を書きます。

def show_all(lines):
    if not lines:
        print("ファイルは存在しますが、中身は空です。")
        return

    for index, line in enumerate(lines, start=1):
        print(f"{index:4}: {line.strip()}")
Python

ここでのポイントは、

この関数は「ファイル名」を知らない
「行のリスト」だけを相手にしている

ということです。

つまり、

ファイルを読む担当 → load_lines
表示する担当 → show_all

と、役割がきれいに分かれています。


ページごとに表示するという発想

10 行ずつ区切って表示してみる

長いファイルを読むとき、
一気に全部出されるとつらいですよね。

そこで、

10 行ずつ表示する
次のページに進むかどうかを聞く

という「ページ表示」を作ってみます。

def show_paged(lines, page_size=10):
    if not lines:
        print("ファイルは存在しますが、中身は空です。")
        return

    total = len(lines)
    current = 0

    while current < total:
        end = min(current + page_size, total)

        for index in range(current, end):
            line_no = index + 1
            print(f"{line_no:4}: {lines[index].strip()}")

        print(f"--- {current + 1} 行目から {end} 行目まで表示しました(全 {total} 行)---")
        cmd = input("続けて表示しますか? (Enter: 続ける / q: 終了): ").strip().lower()

        if cmd == "q":
            print("表示を終了します。")
            break

        current = end
Python

ここで深掘りしたいポイントは、いくつかあります。

total で「全部で何行あるか」を把握している
current で「今どこまで表示したか」を覚えている
page_size 行ずつ進めている
ユーザーに「続けるかどうか」を聞いている

つまり、

「行のリストを、ページという単位で切り分けて見せている」

ということです。


読み込みは一度だけ、表示は選べるようにする

メニューで表示方法を切り替える

ここまでの部品を組み合わせて、
6日目のミニアプリを作ります。

def load_lines(filename):
    with open(filename, "r", encoding="utf-8") as f:
        lines = f.readlines()
    return lines


def show_all(lines):
    if not lines:
        print("ファイルは存在しますが、中身は空です。")
        return

    for index, line in enumerate(lines, start=1):
        print(f"{index:4}: {line.strip()}")


def show_paged(lines, page_size=10):
    if not lines:
        print("ファイルは存在しますが、中身は空です。")
        return

    total = len(lines)
    current = 0

    while current < total:
        end = min(current + page_size, total)

        for index in range(current, end):
            line_no = index + 1
            print(f"{line_no:4}: {lines[index].strip()}")

        print(f"--- {current + 1} 行目から {end} 行目まで表示しました(全 {total} 行)---")
        cmd = input("続けて表示しますか? (Enter: 続ける / q: 終了): ").strip().lower()

        if cmd == "q":
            print("表示を終了します。")
            break

        current = end


def main():
    print("ファイル読み込みアプリ(6日目)")
    filename = input("読み込むファイル名を入力してください: ")

    try:
        lines = load_lines(filename)
    except FileNotFoundError:
        print(f"{filename} が見つかりません。")
        return

    print("表示方法を選んでください。")
    print("1: 全部表示")
    print("2: ページごとに表示(10行ずつ)")
    choice = input("番号: ")

    if choice == "1":
        show_all(lines)
    elif choice == "2":
        show_paged(lines, page_size=10)
    else:
        print("不正な入力です。1 か 2 を選んでください。")


main()
Python

関数ごとの役割を日本語で言い切る

「何をしているか」を自分の言葉で説明する

load_lines
「指定されたファイルを開き、全ての行をリストとして読み込んで返す。」

show_all
「渡された行のリストを、先頭から最後まで行番号付きで全部表示する。」

show_paged
「渡された行のリストを、指定された行数ごとに区切って表示し、
ユーザーに“続けるかどうか”を聞きながらページ送りする。」

main
「ファイル名を入力してもらい、一度だけ行のリストとして読み込む。
そのあと、表示方法(全部/ページごと)を選んでもらい、
対応する表示関数を呼び出す。」

ここまで言えれば、

「read は一度だけ、表示は何度でも」という構造を理解できている状態
になっています。


6日目のまとめ:今日つかんでほしい感覚

今日の本質は、これです。

ファイルからの読み込み(read)は、一度だけでいい。
一度読み込んだ行のリストを、いろんな表示方法に使い回せる。
「読み込み」と「表示」を関数で分けると、アプリの構造が一気に分かりやすくなる。
ページごとに表示するには、「今どこまで表示したか」を変数で覚えておけばいい。

ここまで来ているあなたなら、
7日目に「検索」「フィルタ」「ページ表示」を組み合わせた
かなり本格的な“自分用ファイルビューア”を組み立てられます。

タイトルとURLをコピーしました