Python|openとpathlibのファイルI/O設計の整理法
この記事のポイント
- openとpathlibを活用したファイルI/O設計整理をレビュー視点で体系理解できる
- リソース管理、パス操作、例外責任整理の技法を学べる
- 実務でのファイル設計文化を体系化できる
- PlantUMLでI/O責務依存構造を可視化整理できる
そもそもopenとpathlibとは
PythonのファイルI/Oは長年open()中心で利用されてきましたが、近年はpathlibが高レベルAPIとして設計整理を支援します。
| 機能領域 | 代表API | 主設計責務 |
|---|---|---|
| ファイルオープン | open() | リソース制御責務 |
| パス操作 | pathlib.Path | パス整形・存在確認責務 |
| 例外制御 | try-except | 異常系整理責務 |
open基本例
with open("data.txt", "r") as f:
data = f.read()pathlib基本例
from pathlib import Path
p = Path("data.txt")
data = p.read_text()- pathlibはI/Oとパス処理の責務分離を支援
- openは細粒度のファイル操作制御に依然重要
なぜこれをレビューするのか
ファイルI/O設計は「生存期間と例外責任が混在しやすい領域」です。
レビューアーは以下の整理視点を持つ必要があります。
レビューアー視点
- with構文が適切に適用されているか
- パス組立責務が文字列操作に埋没していないか
- 例外発生時の開放責任が保証されているか
- 事前存在確認 vs 例外捕捉方針が整理されているか
- モジュール化されたI/O責務分離が整理されているか
開発者視点
- 文字列連結でパスを組みがち
- open()単独使用で開放漏洩しがち
- try-exceptが粒度過剰 or 不足
- pathlibを導入し切れずに混在
ファイルI/O崩壊の典型設計臭
崩壊しやすいパターン
- open()を単独使用しclose忘れ
- os.path.join()と文字列連結混在
- 存在確認をifで冗長分岐
- 例外設計が広域try-exceptで肥大
- I/O責務が複数層に分散
崩壊例:開放漏洩型
close忘れ例
f = open("data.txt", "r")
data = f.read()
# close忘れ
@Reviewerファイルリソース開放責務が不備です。with構文を必ず適用してください。
問題点
- リソースリーク発生
- 例外発生時に開放保証消失
崩壊構造モデル:開放漏洩構造
ファイルI/O設計整理の原則
以下の責務整理文化が健全性維持に有効です。
① with構文強制文化
- openは必ずwith内で制御
② pathlib優先文化
- パス操作はPath()で責務明示化
③ I/O責務分離文化
- 読み込み・書き込み処理をAPI単位に整理
④ 例外経路設計文化
- 例外捕捉は呼出境界で整理集中
⑤ 存在確認整理文化
- if存在確認は極力省略 → 例外活用へ
改善例:責務整理版
pathlib整理版
from pathlib import Path
def read_file(file_path: Path) -> str:
return file_path.read_text()
p = Path("data.txt")
data = read_file(p)「with文化+pathlib文化+責務分離文化」
レビューアーは「文字列操作排除文化」を徹底確認すると設計臭抑止できます。
改善構造モデル:責務分離整理
良くない実装例: ケース1(文字列連結型)
文字列連結例
file_path = "/data/" + filename + ".txt"
with open(file_path, "r") as f:
data = f.read()
@Reviewerパス組立に文字列連結を使用しています。pathlib活用で責務分離整理してください。
問題点
- OS依存パス表現
- 拡張性・保守性劣化
改善例:pathlib組立整理
pathlib組立版
from pathlib import Path
p = Path("/data") / f"{filename}.txt"
data = p.read_text()- OS非依存
- パス構造明示化
良くない実装例: ケース2(冗長存在確認)
存在確認例
if os.path.exists(file_path):
with open(file_path, "r") as f:
data = f.read()
else:
raise FileNotFoundError()
@Reviewer存在確認は不要です。open自体がFileNotFoundErrorを発生させます。例外活用に整理してください。
問題点
- 二重確認冗長
- レースコンディション温床
改善例:例外活用整理
例外活用版
try:
data = Path(file_path).read_text()
except FileNotFoundError:
handle_missing_file()- OS依存消失
- 例外経路に整理集中
良くない実装例: ケース3(広域try-except)
try全域例
try:
p = Path(file_path)
with p.open("r") as f:
data = f.read()
process(data)
except Exception as e:
logger.error(e)
@Reviewertry領域が広域化し障害特定が困難です。責務分離して捕捉粒度を整理してください。
問題点
- 捕捉粒度不明確
- 例外原因追跡困難
改善例:例外粒度整理版
例外粒度整理
p = Path(file_path)
try:
data = p.read_text()
except FileNotFoundError:
handle_missing_file()
process(data)- 各責務単位で例外経路整理
観点チェックリスト
まとめ
ファイルI/O設計は「低層ライフサイクル設計の縮図」です。
レビューアーは「with文化・pathlib文化・例外責任文化」を育成指導することで、
障害耐性と保守性の高いファイル設計を安定化できます。

