Python | 2週間で身につく、アプリを作りながら学ぶPythonの基本 - 7日目

Python Python
スポンサーリンク

7日目のゴールとテーマ

7日目のテーマは「アプリのデータを“ファイルに保存して残す”」です。
ここまで作ってきた名簿やお会計、貯金シミュレーターは、プログラムを終了すると全部消えていました。

今日はここに一歩踏み込んで、次の感覚を身につけます。

画面に出すだけでなく、ファイルという“外部の箱”に書き込む
ファイルから読み込んで、リストや辞書に復元する
簡単な「名簿保存アプリ(コンソール版)」を作る

これができると、「アプリっぽさ」が一気に増します。
いよいよ「データが残る世界」に入っていきます。


ファイルって何者?をざっくりイメージする

メモ帳の代わりに、Pythonから書いたり読んだりする

普段、メモ帳アプリでテキストファイルを保存したり開いたりしますよね。
Pythonからも、同じことができます。

メモ帳でやっていることを分解すると、こうなります。

新しいファイルを作る
文字を書き込む
保存する
あとで開いて中身を読む

Pythonでは、この「書く」「読む」をコードでやります。
つまり、プログラムが「自分でメモ帳を操作している」イメージです。


ファイルに文字を書き込んでみる

open と write と close の基本

まずは一番シンプルな「ファイルに文字を書き込む」例からいきます。

file = open("hello.txt", "w", encoding="utf-8")
file.write("こんにちは、Pythonファイルの世界\n")
file.write("7日目もいい感じです\n")
file.close()
Python

このコードを実行すると、同じフォルダに hello.txt というファイルができて、
中には次のような内容が書かれます。

こんにちは、Pythonファイルの世界
7日目もいい感じです

ここで出てきたポイントを一つずつかみ砕きます。

open("hello.txt", "w", encoding="utf-8") は、「hello.txt という名前のファイルを、書き込みモードで開く」という意味です。
最初の引数がファイル名、 "w" がモード、 encoding="utf-8" は文字コード(日本語を正しく扱うためのおまじない)です。

"w" モードは「書き込み専用で開く。もしファイルがあれば中身を消してから書く」という動きです。
すでに同名のファイルがあると上書きされるので、そこは意識しておきましょう。

file.write(...) で、実際に文字列を書き込みます。
改行は自動では入らないので、必要なら \n を自分で付けます。

最後に file.close() で、「もうこのファイルは使いません」と閉じます。
これを忘れると、環境によっては書き込みが完全に終わらなかったり、他のプログラムから開けなくなったりすることがあります。


with 文で「閉じ忘れ」を防ぐ

Pythonらしい安全な書き方

毎回 close() を書くのは面倒ですし、エラーが起きたときに close() までたどり着かないこともあります。
そこでよく使われるのが with 文です。

with open("hello.txt", "w", encoding="utf-8") as file:
    file.write("with 文で書き込んでいます\n")
    file.write("この書き方だと、自動で close してくれます\n")
Python

with ... as ...: の形で書くと、ブロックを抜けたタイミングで自動的に close() してくれます。
「開いたら必ず閉じる」を言語側が保証してくれるので、実務でもほぼこの書き方一択です。

7日目のうちに、「ファイルを触るときは基本 with を使う」と覚えてしまって大丈夫です。


ファイルから文字を読み込む

read と readlines の基本

次は「読む」側です。
さっき書いた hello.txt を読み込んでみましょう。

with open("hello.txt", "r", encoding="utf-8") as file:
    text = file.read()

print("ファイルの中身は次の通りです。")
print(text)
Python

ここでは "r" モードを使っています。
"r" は「読み込み専用」です。

file.read() は、「ファイルの中身を全部まとめて1つの文字列として読み込む」関数です。
小さなテキストファイルならこれで十分です。

一行ずつ扱いたい場合は、readlines() もよく使われます。

with open("hello.txt", "r", encoding="utf-8") as file:
    lines = file.readlines()

print("行ごとに表示します。")
for line in lines:
    print("1行:", line, end="")
Python

readlines() は、「各行を要素とするリスト」を返します。
行末の改行文字 \n も含まれているので、print するときに end="" を付けて二重改行にならないようにしています。

ここでの重要ポイントは、「ファイルの中身は最終的に文字列として扱う」ということです。
そこから必要に応じて数字に変換したり、区切り文字で分割したりしていきます。


名簿をファイルに保存するための形式を決める

まずは「1行1人、カンマ区切り」というシンプルなルール

5日目・6日目で作った名簿アプリを思い出してください。
あれは、メモリ上では「辞書のリスト」という形で持っていました。

ファイルに保存するときは、「文字列としてどう表現するか」を決める必要があります。
今日はシンプルに、「1行が1人分」「カンマで区切る」というルールにします。

例えば、こんな感じです。

太郎,20
花子,18
次郎,22

この形式なら、読み込んだときに

行を一行ずつ読む
カンマで分割する
左を名前、右を年齢として扱う

という流れで、また辞書のリストに戻せます。

「どう保存するか」を先に言葉で決めてからコードに落とす。
これはアプリ設計でとても大事なステップです。


名簿をファイルに書き出す関数を書く

people リストを受け取って、テキストファイルに保存する

まずは「保存する側」の関数を作ります。
6日目までの流れを踏まえて、関数として切り出してみましょう。

def save_people_to_file(people, filename):
    with open(filename, "w", encoding="utf-8") as file:
        for person in people:
            line = person["name"] + "," + str(person["age"]) + "\n"
            file.write(line)
Python

この関数は、「people リスト」と「ファイル名」を受け取って、
中身をカンマ区切りで書き出します。

ループの中でやっていることを丁寧に見ると、

person["name"] で名前を取り出す
str(person["age"]) で年齢を文字列に変換する
名前 + "," + 年齢 + "\n" で「太郎,20\n」のような1行分の文字列を作る
それを file.write で書き込む

という流れです。

ここでの重要ポイントは、「ファイルに書くのはあくまで文字列」ということです。
辞書やリストのままでは書けないので、「文字列に変換するルール」を自分で決めています。


ファイルから名簿を読み込む関数を書く

テキストを読んで、辞書のリストに復元する

次は「読み込む側」です。
さっき決めた形式に従って、ファイルから people リストを作り直します。

def load_people_from_file(filename):
    people = []

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

                if line == "":
                    continue

                parts = line.split(",")

                if len(parts) != 2:
                    continue

                name = parts[0]
                age_text = parts[1]

                try:
                    age = int(age_text)
                except ValueError:
                    continue

                person = {"name": name, "age": age}
                people.append(person)

    except FileNotFoundError:
        people = []

    return people
Python

少し長く見えますが、やっていることは順番に追えばシンプルです。

最初に people = [] で空のリストを用意する。
open(..., "r") でファイルを読み込みモードで開く。
for line in file: で、ファイルを一行ずつ処理する。
line.strip() で前後の空白や改行を取り除く。
空行なら continue でスキップする。
line.split(",") でカンマで分割して、配列 parts を得る。
要素数が2でなければおかしいのでスキップする。
parts[0] を名前、parts[1] を年齢文字列として取り出す。
int(...) で年齢を整数に変換する。変換できなければスキップする。
辞書 {"name": name, "age": age} を作って people に追加する。

そして、外側を try ... except FileNotFoundError で囲んでいます。
これは、「ファイルがまだ存在しない場合(初回起動など)は、空の名簿として扱う」というためのものです。

ここでの重要ポイントは二つです。

一つ目、「ファイルの内容が“きれい”とは限らない前提で書いている」こと。
空行やおかしな形式の行があっても、アプリ全体が落ちないように continuetry/except で防御しています。

二つ目、「ファイルがない=エラーではなく、空のデータとして扱う」という設計にしていること。
これは現実のアプリでもよくあるパターンです。


7日目のミニアプリ:ファイル付き名簿アプリ(コンソール版)

起動時に読み込み、終了時に保存する

ここまでの部品を組み合わせて、「データが残る名簿アプリ」を作ります。

def input_people():
    people = []

    while True:
        name = input("名前を入力してください(終了するには空のままEnter): ")

        if name == "":
            print("入力を終了します。")
            break

        age_text = input("年齢を入力してください: ")
        age = int(age_text)

        person = {"name": name, "age": age}
        people.append(person)

    return people


def print_people(people):
    print("=== 名簿一覧 ===")

    if len(people) == 0:
        print("誰も登録されていません。")
    else:
        for i in range(len(people)):
            person = people[i]
            print(str(i + 1) + "人目: " + person["name"] + "(" + str(person["age"]) + "歳)")


def save_people_to_file(people, filename):
    with open(filename, "w", encoding="utf-8") as file:
        for person in people:
            line = person["name"] + "," + str(person["age"]) + "\n"
            file.write(line)


def load_people_from_file(filename):
    people = []

    try:
        with open(filename, "r", encoding="utf-8") as file:
            for line in file:
                line = line.strip()
                if line == "":
                    continue

                parts = line.split(",")
                if len(parts) != 2:
                    continue

                name = parts[0]
                age_text = parts[1]

                try:
                    age = int(age_text)
                except ValueError:
                    continue

                person = {"name": name, "age": age}
                people.append(person)

    except FileNotFoundError:
        people = []

    return people


FILENAME = "people.txt"

print("=== 名簿アプリ 7日目(ファイル保存バージョン) ===")

people = load_people_from_file(FILENAME)
print("前回までの名簿を読み込みました。")
print_people(people)

print("新しく人を追加できます。")
new_people = input_people()

people.extend(new_people)

print("最終的な名簿です。")
print_people(people)

save_people_to_file(people, FILENAME)
print("名簿をファイルに保存しました。プログラムを終了します。")
Python

このアプリの流れを言葉で整理すると、こうなります。

起動したら、まず people.txt から名簿を読み込む。
読み込んだ名簿を表示する。
ユーザーに新しい人を入力してもらう。
既存の名簿に新しい人を追加する。
最終的な名簿を表示する。
名簿全体を people.txt に保存して終了する。

これで、「一度登録した名簿が、次に起動したときも残っている」状態になります。
コンソールアプリではありますが、立派に「データを持つアプリ」です。


7日目で一番大事な感覚

「メモリの外に出した瞬間、アプリは一段階“現実寄り”になる」

今日あなたに持ってほしい感覚はこれです。

これまでは、プログラムを終了するとデータは消えていました。
それは「メモリの中だけで完結している世界」です。

ファイルに書き出して、次回起動時に読み込むようにした瞬間、
アプリは「時間をまたいでデータを持つ存在」になります。

ファイルは、そのための一番シンプルな手段です。

ファイルを開くときは with open(..., モード, encoding="utf-8") as f:
書くときは f.write(文字列)
読むときは f.read()for line in f:
そして、「どんな形式で保存するか」を自分で決める

このあたりがふわっとでもつかめていれば、7日目としては十分すぎます。


7日目のまとめ

今日のキーポイントを短くまとめると、こうなります。

ファイルは「プログラムの外にある、長期保存用の箱」。
open(..., "w") で書き込み、open(..., "r") で読み込み。
with 文を使うと、自動で close() されて安全。
「1行1件、カンマ区切り」のように、自分で保存形式を決める。
辞書のリストを文字列に変換して書き出し、読み込むときにまた辞書のリストに戻す。

もし余裕があれば、今日の名簿アプリに次のような工夫をしてみてください。

年齢だけでなく「メールアドレス」も保存してみる
保存形式を「タブ区切り」に変えてみる
ファイル名をユーザーに入力してもらい、複数の名簿ファイルを使い分けられるようにする

ここまで来ると、もう「ただの練習コード」ではなく、
自分のデータをちゃんと持てる“小さなアプリ”になっています。
この感覚を土台に、8日目以降はさらにアプリ寄りの世界に踏み込んでいきましょう。

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