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

ストーン
ストーン

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

AG先生
AG先生

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

os.pathからpathlibへの進化を図解で学ぶAG先生とストーンさん
os.pathからpathlibへの進化を図解で学ぶAG先生とストーンさん

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}")

AG先生
AG先生

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

2. 実践編:ファイルの存在確認とエラーハンドリング

ストーン
ストーン

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

AG先生
AG先生

さすがストーンさん、実戦的な悩みですね。`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での捕捉)")
AG先生
AG先生

`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))
AG先生
AG先生

そうなんですよね。歴史の長いライブラリの中には、パスとして「単なる文字列(`str`)」しか受け付けないものもまだ存在します。<br>でも焦らなくて大丈夫。そういう時は `str(current_script)` のようにキャスト(型変換)してあげれば、問題なく古い関数にも渡せますよ!

📚 AG先生の今日の一冊

『独学プログラマー Python言語の基本から仕事のやり方まで』

AG先生
AG先生

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

私が書きました!
ストーン

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