Kodokon kodokon.com

ファイルとモジュール:with、import、構成

withでファイルをきれいに読み書きし、JSONをやり取りし、コードをインポート可能なモジュールへと整理しましょう。

10 分 · 3 問

このレッスンを Kodokon で開く

ファイルの読み書きは、実際のプログラムの日々の糧です。エクスポート、ログ、設定などがそうです。withキーワードはファイルを開き、ブロックの途中でエラーが起きたとしても必ず閉じることを保証します。ファイルを開く実務的なやり方はこれだけです。これなしでは、close()を忘れるとデータが壊れたり、システムの資源を使い果たしたりしかねません。

PYTHON
lines = ["alpha", "beta", "gamma"]

with open("notes.txt", "w", encoding="utf-8") as f:
    for line in lines:
        f.write(line + "\n")

with open("notes.txt", encoding="utf-8") as f:
    content = f.read()

print(content)
'w'モードは中身を上書きして書き込む。モードを書かなければ読み込みになる

構造化されたデータには、自分でフォーマットを考え出してはいけません。標準ライブラリのjsonモジュールが、辞書やリストをテキストに変換し、また元に戻します。プログラム、API、設定ファイルのあいだで使われる、世界共通のやり取りの形式です。

PYTHON
import json

config = {"debug": True, "retries": 3}

with open("config.json", "w", encoding="utf-8") as f:
    json.dump(config, f, indent=2)

with open("config.json", encoding="utf-8") as f:
    loaded = json.load(f)

print(loaded["retries"])  # 3
json.dumpが構造を書き出し、json.loadがそれを組み立て直す

モジュールとは、単に一つの.pyファイルのことです。import billingbilling.pyを読み込み、その中身を一度だけ実行します。責務ごとにコードを整理しましょう。請求のためのモジュール、保存のためのモジュール、というふうにです。そしてimport文はファイルの先頭にまとめておきましょう。if __name__ == "__main__"というテストは二つの状況を区別します。直接実行されたとき、ファイルはこのブロックを実行します。インポートされたときは、それを無視します。

PYTHON
def compute_total(prices):
    return round(sum(prices), 2)

def main():
    print(compute_total([9.99, 4.5, 20.0]))

if __name__ == "__main__":
    main()
billing.pyの中身:どこからでもインポートでき、直接実行もできる
BASH
python billing.py
こうして実行すると、ファイルはmain()を実行する。インポートされたときは何もしない

理解度チェック

このレッスンの要点をしっかり覚えているか確認しましょう。

  1. open()だけを使うのに比べて、with open(...)の主な利点は何ですか?
    • エラーが起きた場合でも、ファイルが自動的に閉じられる
    • ファイルの読み込みが速くなる
    • モードに関わらず、存在しないファイルが作成される
  2. "w"モードと"a"モードの違いは何ですか?
    • "w"は既存の中身を上書きし、"a"は末尾に追記する
    • "w"はテキストを書き、"a"はバイナリを書く
    • "w"はファイルを作り、"a"は存在しないと失敗する
  3. if __name__ == "__main__"というテストは何のためにありますか?
    • ファイルの名前が本当にmain.pyかどうかを確かめるため
    • ファイルが直接起動されたときだけブロックを実行するため
    • ほかのファイルからモジュールがインポートされるのを防ぐため