ファイルに書き込む

このレッスンで作るもの — 支出の行をファイルに書き出し、その場で読み戻して確かめる write_records を作ります。

ファイルに書き込む

前回はファイルを読みました。今回は書きます。おこづかい帳で言えば、アプリを終了するときに記録を残す部分にあたります。

書き込みも open から始まります。違うのはモードだけで、読みの "r" に対して書きは "w" を指定します。

f = open("kakeibo.txt", "w", encoding="utf-8") f.write("りんご,120,食費") f.close()

write はかっこの中の文字列をファイルに書き出します。print と似ていますが、決定的な違いが 1 つあります。

print は行の終わりに自動で改行を付けますが、write は付けません。改行が必要なら自分で \n を書きます。

上書きモードと追記モード

"w"上書き のモードです。すでに中身があるファイルを "w" で開いた瞬間、中身は空になります。書く前から消えるので、開くだけで消えてしまう点に注意します。

f = open("kakeibo.txt", "w", encoding="utf-8") f.close()

これだけで、元の記録は失われます。うっかり "r""w" を打ち間違えると起きる事故です。

末尾に足したいときは "a" という追記モードを使います。おこづかい帳では「全件をまとめて書き直す」ほうが管理が楽なので、このコースでは "w" を使います。

モード意味
"r"読み込む。ファイルが無いとエラー
"w"書き込む。中身は消えて新しくなる
"a"末尾に追記する

複数行をまとめて書く

支出が何件もあるときは、リストの各要素を 1 行ずつ書きます。ここで役に立つのが第 7 章までに何度も使った join です。

lines = ["りんご,120,食費", "みかん,80,食費"] text = "\n".join(lines)

"\n".join(lines) は要素の あいだ だけに改行を挟むので、"りんご,120,食費\nみかん,80,食費" になります。末尾に改行は付きません。第 1 章から一貫している「末尾に改行を付けない」規則がここでも生きます。

for で 1 行ずつ write する書き方もできますが、その場合は自分で \n を足すことになり、最後の行だけ改行を付けないという面倒な場合分けが要ります。join のほうが素直です。

diagram (will load when visible)

書いたら読み戻して確かめる

書き込みの怖いところは、失敗しても静かなこと です。パスを打ち間違えても、意図しない場所にファイルができるだけで、エラーは出ません。

そこでこの演習では、書いた直後に同じパスを読み戻し、その内容を戻り値にします。読み戻せたということは、確かに書けたということです。学習環境の都合でこの形にしていますが、実際の開発でも保存処理のテストは同じ考え方で書きます。

「書けたつもり」がいちばん危険です。読み戻して一致を確かめるまでは、保存できたとは言えません。

動きを追ってみる

write_records("/tmp/kakeibo.txt", ["りんご,120,食費", "みかん,80,食費"]) の流れを追います。

  1. join"りんご,120,食費\nみかん,80,食費" を作る
  2. /tmp/kakeibo.txt"w" で開く。中身は空になる
  3. write で文字列を書き出し、close で閉じる
  4. 同じパスを "r" で開き、read で中身を読む
  5. "りんご,120,食費\nみかん,80,食費" が戻り値になる

リストが空 [] のときは join の結果も空文字 "" になり、中身が空のファイルができます。読み戻すと "" が返ります。

よくある間違い

  1. write に改行を期待するwrite("りんご") を 2 回呼んでも 2 行にはならず、りんごりんご と横につながります。改行は自分で書きます。
  2. write にリストを渡すf.write(["a", "b"])TypeError になります。write が受け取れるのは文字列だけなので、先に join で 1 本にします。
  3. 数値をそのまま渡すf.write(120)TypeError です。金額を書くときは str(120) で文字列にしてからにします。

"w" で開いた時点で中身が消える、という性質もよく忘れられます。大事なファイルのパスを渡す前に、一度 /tmp の適当な名前で試すのが安全です。

やってみよう

関数 write_records(path, lines) を実装してください。lines は文字列のリストです。"\n".join(lines) で 1 本の文字列にしてから path に書き出し、同じファイルを読み戻して、その内容の文字列を return します。

文字コードは encoding="utf-8" を指定します。lines が空リストのときは空文字 "" が返る形になっていれば正解です。末尾に余計な改行を足さないよう気をつけてください。

要件

  1. 関数名は write_records で、引数は path と lines の 2 つ
  2. lines を "\n".join で 1 本の文字列にしてから書き出す
  3. path を書き込みモードで開き、write で書き出して close する
  4. 同じ path を読み込みモードで開き、read の結果を return する
  5. open には encoding="utf-8" を指定する

入出力例

write_records("/tmp/kakeibo_write_1.txt", ["りんご,120,食費","みかん,80,食費"]) → "りんご,120,食費 みかん,80,食費" write_records("/tmp/kakeibo_write_2.txt", ["ノート,200,日用品"])"ノート,200,日用品" write_records("/tmp/kakeibo_write_3.txt", [])"" write_records("/tmp/kakeibo_write_4.txt", ["バス,220,交通費","映画,1800,娯楽","洗剤,380,日用品"]) → "バス,220,交通費 映画,1800,娯楽 洗剤,380,日用品" write_records("/tmp/kakeibo_write_5.txt", ["もらいもの,0,その他"])"もらいもの,0,その他"

ヒント

生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア
編集 LuaGate編集部
main.py
main.py
学習モード

メモ

ファイルに書き込む

⌘S で保存