1. ファイルの書き込みと読み込み
open(ファイル名, モード) でファイルを開きます。
モードは "w"(書き込み), "r"(読み込み), "a"(追記)です。
with 文を使うと、ブロックを抜けた時点で自動的にファイルが閉じられます。
💡 with文の重要性: with open(...) as f: を使うと、例外が発生してもファイルが確実に閉じられます。f.close() を書き忘れるバグを防ぐためにも、常に with を使う習慣をつけましょう。
📋 "w" と "a" の使い分け: どちらも f.write() で書き込めますが、ファイルを開いた瞬間の動作が異なります。
"w"(write)— ファイルを新規作成または上書きします。既存のファイルがあれば内容が全て消えます。"a"(append)— ファイルが存在すれば末尾に追記します。存在しなければ新規作成します。
患者ログを日々追加していく場合は "a"、毎回新しいデータで置き換えるレポート出力には "w" が適しています。
2. 行単位の読み込み
f.read() はファイル全体を1つの文字列として読みます。一方、大きなファイルでは行単位で処理する方が効率的です。
for line in f:— 1行ずつ順番に読む(大ファイルでもメモリに全部乗らない)f.readlines()— 全行を文字列のリストとして読む(後で添字アクセスや len() が使える)
💡 文字列ログから数値を取り出すには:
split() を連続して使うと、フォーマットが決まったログから数値部分を抽出できます。
line = "2026-05-01 15:00, SpO2=93%, HR=110, BP=145/95"
# "SpO2=" の後ろを取得 → "93%, HR=110, BP=145/95"
# さらに "%" の前を取得 → "93" → int() で数値化
spo2_val = int(line.split("SpO2=")[1].split("%")[0]) # 93
# "HR=" の後ろを取得 → "110, BP=145/95"
# さらに "," の前を取得 → "110" → int() で数値化
hr_val = int(line.split("HR=")[1].split(",")[0]) # 110
数値条件の判定には必ず int() に変換してから比較しましょう。より複雑なパターンには import re(正規表現、L18)、構造化データには後述の CSV 処理 が適しています。
3. CSV の読み書き
csv モジュールを使うと、CSV形式のデータを簡単に扱えます。
csv.DictWriter で辞書リストをCSVに書き出し、
csv.DictReader で読み込むとヘッダーをキーとした辞書として扱えます。
📋 CSV 書き込みで使う3つのポイント:
newline=""—open()に渡す引数。Windows では改行コードが二重になる問題を防ぐために必要です。CSV ファイルを書くときは常に指定する習慣をつけましょう。writer.writeheader()—fieldnamesで指定した列名を1行目(ヘッダー行)として書き込みます。writer.writerows(データリスト)— 辞書のリストをまとめて書き込みます。for row in records: writer.writerow(row)と同じ意味ですが1行で書けます。
🚀 実務では Pandas を使うことが多い
CSV や Excel を扱う実務・AI 開発では Pandas(import pandas as pd)というライブラリがよく使われます。
import pandas as pd
df = pd.read_csv("patients.csv") # 1行で読み込み
print(df["spo2"].mean()) # 平均も1行
df[df["spo2"] < 95] # 条件フィルタも直感的
Pandas は標準ライブラリではないため別途インストールが必要ですが(pip install pandas)、このコース(Pyodide環境)ではそのまま使えます(実行に時間かかるため注意)。今は csv モジュールでファイル操作の基礎を押さえておけば、Pandas にスムーズに移行できます。
4. os.path でファイルパスを操作する
os.path モジュールを使うと、ファイルの存在確認・パス結合・拡張子取得などが
OS(Windows/Mac/Linux)に依存せず書けます。
💡 医療AI文脈: DICOMファイルやCSVデータセットを読み込む際、os.path.join() でパスを組み立て、os.path.exists() で存在確認してから開くのがベストプラクティスです。
5. 練習問題
患者データをファイルに書き込む
患者名・年齢・診断名のリストを /tmp/patients.txt に書き込み、その後読み込んで表示してください。各行のフォーマットは「名前,年齢,診断名」です。
ヒントを見る(答え+解説)
patients = [
("田中太郎", 45, "高血圧"),
("山田花子", 62, "糖尿病"),
("佐藤次郎", 33, "肺炎"),
]
filename = "/tmp/patients.txt"
with open(filename, "w", encoding="utf-8") as f:
for p in patients:
f.write(f"{p[0]},{p[1]},{p[2]}\n")
print("=== 患者ファイル内容 ===")
with open(filename, "r", encoding="utf-8") as f:
print(f.read())
# → 田中太郎,45,高血圧
# → 山田花子,62,糖尿病
# → 佐藤次郎,33,肺炎
with open() 構文はファイルを自動でクローズします。書き込みは "w"、読み込みは "r" モードを使い、日本語を含む場合は encoding="utf-8" を指定しましょう。
CSVから検査値を読み込んで統計表示
CSVファイルに血糖値データを書き込み、csv.DictReader で読み込んで平均・最大・最小を表示してください。
ヒントを見る(答え+解説)
import csv
csv_file = "/tmp/glucose.csv"
records = [
{"date": "2026-05-01", "time": "朝", "glucose": 95},
{"date": "2026-05-01", "time": "昼", "glucose": 140},
{"date": "2026-05-01", "time": "夕", "glucose": 165},
{"date": "2026-05-02", "time": "朝", "glucose": 102},
{"date": "2026-05-02", "time": "昼", "glucose": 155},
]
with open(csv_file, "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=["date", "time", "glucose"])
writer.writeheader()
writer.writerows(records)
with open(csv_file, "r", encoding="utf-8") as f:
rows = list(csv.DictReader(f))
values = [int(row["glucose"]) for row in rows]
print(f"平均: {sum(values)/len(values):.1f} mg/dL")
print(f"最大: {max(values)} mg/dL")
print(f"最小: {min(values)} mg/dL")
# → 平均: 131.4 mg/dL / 最大: 165 mg/dL / 最小: 95 mg/dL
穴埋め箇所は values = [int(row["glucose"]) for row in rows] の1行だけです。
テンプレートの書き込み部分の解説:
newline=""— Windows 環境で改行コードが二重になるのを防ぐ。CSV 書き込み時の定型句です。writer.writeheader()—fieldnamesに渡した列名をCSVの1行目(ヘッダー行)として書き込みます。writer.writerows(records)— 辞書のリストを一括で書き込みます(for row in records: writer.writerow(row)と同じ)。
csv.DictReader は各行を列名→値の辞書として読み込みます。CSVの値はすべて文字列なので、数値計算には必ず int() や float() で変換が必要です。
ファイルの存在確認と安全な読み込み
os.path.exists() でファイルが存在するか確認してから読み込む関数 safe_read(filepath) を作ってください。存在しない場合は None を返します。
ヒントを見る(答え+解説)
import os
def safe_read(filepath):
"""ファイルが存在すれば内容を返し、なければNoneを返す"""
if not os.path.exists(filepath):
print(f"ファイルが見つかりません: {filepath}")
return None
with open(filepath, "r", encoding="utf-8") as f:
return f.read()
with open("/tmp/test.txt", "w") as f:
f.write("テストデータ\n血糖値: 120 mg/dL")
result = safe_read("/tmp/test.txt")
print("存在するファイル:", result)
result2 = safe_read("/tmp/no_such_file.txt")
print("存在しないファイル:", result2)
# → 存在するファイル: テストデータ\n血糖値: 120 mg/dL
# → ファイルが見つかりません: /tmp/no_such_file.txt
# → 存在しないファイル: None
os.path.exists() でファイルの存在を確認してから開くことでエラーを防ぎます。None を返すことで呼び出し側が「ファイルなし」を判断できる、安全な設計パターンです。
まとめ
このレッスンのポイント
with open(path, mode, encoding="utf-8") as f:でファイルを安全に開く- モード:
"r"(読込),"w"(書込・上書き),"a"(追記) f.read()で全体読込、for line in f:で行単位csv.DictWriter/csv.DictReaderで辞書形式のCSV処理os.path.join()でパス結合、os.path.exists()で存在確認
自由に試してみましょう:
完了するとトップページに進捗が表示されます
