Python pathlib入門:初心者が躓くポイントとos.pathからの脱却

AG先生、最近Pythonでファイルを読み書きするコードを書いているんですけど、パスの指定でたまにエラーになるんですよね。スラッシュの有無とか、フォルダの結合とか……。あと `os.path` っていうのを使っているんですが、これって今も主流なんですか?

ストーンさん、いいところに気づきましたね! `os.path` も決して悪くないのですが、Python 3.4以降(最新バージョンの3.14等でも推奨されています)は、もっと便利で直感的な `pathlib` というモダンなモジュールが用意されているんですよ。今日は文字列のパズルから卒業して、オブジェクトとしてパスを扱う賢い方法を学んでみましょう!

1. 基本編:パスの作成と文字列結合(os.path)からの脱却
ソースコード
import os
from pathlib import Path
# === 1. 基本編:パスの作成と文字列結合(os.path)からの脱却 ===
# 従来のやり方(os.path.join)
base_dir_str = "/usr/local"
sub_dir_str = "bin"
file_name_str = "script.py"
legacy_path = os.path.join(base_dir_str, sub_dir_str, file_name_str)
print(f"os.path.join: {legacy_path}")
# 初心者がよくやる文字列結合(バグの元)
bad_path = base_dir_str + "/" + sub_dir_str + "/" + file_name_str
print(f"String concatenation: {bad_path}")
# 新しいやり方(pathlibの `/` 演算子)
base_dir = Path("/usr/local")
modern_path = base_dir / "bin" / "script.py"
print(f"pathlib (/ operator): {modern_path}")

従来の `os.path.join` だと、カッコの中にカンマ区切りで変数を並べないといけないですよね。それに、面倒くさがって `+ “/"` で無理やり文字列を足し算すると、スラッシュが重複したり抜けたりしてバグの温床になります。<br>でも `pathlib` の `Path` オブジェクトを作れば、なんと割り算と同じ `/` 演算子で直感的にパスを繋げられるんです!とっても「Pythonic」で読みやすいコードになりますよ。
2. 実践編:ファイルの存在確認とエラーハンドリング

確かに `/` で繋げるのは驚くほどスマートですね!でも、パスを作った後に「そのファイルが本当に存在するか」をチェックしたい時はどうするんですか?よく `FileNotFoundError` でプログラムが死んじゃうんです……。

さすがストーンさん、実戦的な悩みですね。`pathlib` なら存在確認もメソッド一つで簡単です。また、Python特有の「EAFP(許可を求めるより許しを請うほうが容易)」という例外処理の考え方も見てみましょう。
ソースコード
# === 2. 実践編:ファイルの存在確認とエラーハンドリング ===
# 存在しないファイルへのパスを作成
target_file = Path("non_existent_folder") / "secret_data.txt"
# 事前確認パターン(.exists() を使う)
if not target_file.exists():
print(f"Check 1: {target_file} は存在しません。(.exists()での確認)")
# 例外処理パターン(EAFP: 許可を求めるより許しを請うほうが容易)
try:
with target_file.open("r", encoding="utf-8") as f:
f.read()
except FileNotFoundError:
print(f"Check 2: {target_file} が見つかりませんでした。(try-exceptでの捕捉)")

`target_file.exists()` というように、パス自身が「自分が存在するかどうか」を知るメソッドを持っています。これがオブジェクト指向の強みですね。<br>ただし、確認した直後にファイルが消される可能性などもあるため、安全性を高めるなら `try-except` で `FileNotFoundError` をキャッチしつつ開く(下側の書き方)のが、Pythonでは好まれるアプローチなんですよ。

3. 応用編:古いライブラリとの互換性

`pathlib` が便利なのはよく分かりました!これからは全部これにします。……あれ?でも古い外部ライブラリの関数にこの `Path` を渡したら、エラーで怒られてしまいました。
ソースコード
# === 3. 応用編:古いライブラリとの互換性 ===
def dummy_legacy_function(file_path_str):
"""パスオブジェクトを受け取らず、文字列型のみをサポートする古い関数のダミー"""
if not isinstance(file_path_str, str):
raise TypeError("path strings must be str, not Path")
print(f"[Legacy API] Processing file: {file_path_str}")
current_script = Path(__file__)
# str() でキャストして渡す
print("-> str() でキャストして渡すと成功します:")
dummy_legacy_function(str(current_script))

そうなんですよね。歴史の長いライブラリの中には、パスとして「単なる文字列(`str`)」しか受け付けないものもまだ存在します。<br>でも焦らなくて大丈夫。そういう時は `str(current_script)` のようにキャスト(型変換)してあげれば、問題なく古い関数にも渡せますよ!
📚 AG先生の今日の一冊
『独学プログラマー Python言語の基本から仕事のやり方まで』

これからPythonの標準ライブラリをもっと使いこなしたいストーンさんにピッタリの一冊。細かい文法だけでなく、「どう書けばプロらしいコード(Pythonic)になるか」が実践的に学べる良書です。ファイル操作の章もぜひ読み直してみてくださいね!

「プログラミングの『わからない』を『楽しい』に変える」をモットーに、Pythonの基礎からA*アルゴリズムまで幅広く発信しています。現在はAIエージェント(Antigravity)と共に、人間とAIの共生する開発スタイルを模索中です。
当サイトについて







ディスカッション
コメント一覧
まだ、コメントがありません