9
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

まだos.path.join()を使っていますか?

Python 3.4以降はpathlibが標準。オブジェクト指向でパスを扱えて、可読性が格段に向上するよ。

# Before (os.path)
import os
path = os.path.join("folder", "subfolder", "file.txt")
basename = os.path.basename(path)
exists = os.path.exists(path)

# After (pathlib)
from pathlib import Path
path = Path("folder") / "subfolder" / "file.txt"
basename = path.name
exists = path.exists()

基本操作

パス作成

from pathlib import Path

# / 演算子でパス結合
p = Path("folder") / "subfolder" / "file.txt"
# folder/subfolder/file.txt (UNIX)
# folder\subfolder\file.txt (Windows)

# 特別なパス
Path.cwd()   # 現在のディレクトリ
Path.home()  # ホームディレクトリ

パス情報の取得

p = Path("/home/user/documents/report.pdf")

p.name      # 'report.pdf'
p.stem      # 'report'
p.suffix    # '.pdf'
p.parent    # Path('/home/user/documents')
p.parts     # ('/', 'home', 'user', 'documents', 'report.pdf')

# 複数の拡張子
Path("file.tar.gz").suffixes  # ['.tar', '.gz']

パス判定

p = Path("folder/file.txt")

p.exists()       # 存在するか
p.is_file()      # ファイルか
p.is_dir()       # ディレクトリか
p.is_absolute()  # 絶対パスか

ファイル操作

読み書き

p = Path("data.txt")

# 書き込み
p.write_text("Hello, pathlib!", encoding="utf-8")

# 読み込み
content = p.read_text(encoding="utf-8")

# バイナリ
p.write_bytes(b"Binary data")
data = p.read_bytes()

ファイル作成・削除

# 空ファイル作成
p.touch()

# 削除
p.unlink()
p.unlink(missing_ok=True)  # 存在しなくてもエラーにならない

ディレクトリ操作

作成

# 単一ディレクトリ
Path("folder").mkdir()

# 親ディレクトリも含めて作成
Path("folder/sub1/sub2").mkdir(parents=True, exist_ok=True)

一覧取得

p = Path(".")

# 直下のみ
for item in p.iterdir():
    print(item.name, "dir" if item.is_dir() else "file")

削除

Path("empty_folder").rmdir()  # 空のディレクトリのみ

# 中身ごと削除はshutil
import shutil
shutil.rmtree(Path("folder"))

glob(パターンマッチ)

p = Path(".")

# 直下のtxtファイル
for f in p.glob("*.txt"):
    print(f)

# 再帰的に検索
for f in p.rglob("*.txt"):  # **/*.txt と同じ
    print(f)

# 複数パターン
for f in p.glob("*.{txt,md}"):  # ❌ これは動かない
    pass

# 代わりに
for f in p.iterdir():
    if f.suffix in [".txt", ".md"]:
        print(f)

パス変換

p = Path("folder/file.txt")

p.with_name("other.txt")    # folder/other.txt
p.with_suffix(".md")        # folder/file.md
p.with_stem("renamed")      # folder/renamed.txt (Python 3.9+)

絶対パス・相対パス

# 絶対パスに変換
Path("./folder/../folder/file.txt").resolve()
# → /home/user/project/folder/file.txt

# 相対パスに変換
base = Path("/home/user")
full = Path("/home/user/docs/file.txt")
full.relative_to(base)  # docs/file.txt

統計情報

stat = Path("file.txt").stat()

stat.st_size   # ファイルサイズ(バイト)
stat.st_mtime  # 最終更新時刻(UNIX時間)
stat.st_ctime  # 作成時刻

os.path → pathlib 対応表

os.path pathlib
os.path.join(a, b) Path(a) / b
os.path.basename(p) p.name
os.path.dirname(p) p.parent
os.path.splitext(p) (p.stem, p.suffix)
os.path.exists(p) p.exists()
os.path.isfile(p) p.is_file()
os.path.isdir(p) p.is_dir()
os.path.abspath(p) p.resolve()
os.path.expanduser("~") Path.home()
os.getcwd() Path.cwd()
os.listdir(p) list(p.iterdir())
glob.glob("*.txt") Path(".").glob("*.txt")

実践パターン

特定拡張子のファイルを処理

def process_files(directory: Path, extension: str):
    for file_path in directory.rglob(f"*{extension}"):
        content = file_path.read_text()
        # 処理...

バックアップ作成

import shutil

def backup_file(file_path: Path) -> Path:
    backup_path = file_path.with_suffix(file_path.suffix + ".bak")
    shutil.copy2(file_path, backup_path)
    return backup_path

設定ファイルの場所

def get_config_path() -> Path:
    # XDG準拠
    config_dir = Path.home() / ".config" / "myapp"
    config_dir.mkdir(parents=True, exist_ok=True)
    return config_dir / "config.json"

一時ファイル

from pathlib import Path
import tempfile

with tempfile.TemporaryDirectory() as tmpdir:
    tmp_path = Path(tmpdir)
    (tmp_path / "temp.txt").write_text("Temporary content")
    # スコープを抜けると自動削除

型ヒント

from pathlib import Path

def process(file_path: Path) -> None:
    ...

def list_files(directory: Path) -> list[Path]:
    return list(directory.iterdir())

注意点

文字列への変換

p = Path("folder/file.txt")

# 文字列が必要な場合
str(p)  # "folder/file.txt"

# os.fspath でも可
import os
os.fspath(p)

Windowsパス

# Windowsでも / で書ける
p = Path("C:/Users/name/file.txt")  # OK

# バックスラッシュはエスケープが必要
p = Path("C:\\Users\\name\\file.txt")  # OK
p = Path(r"C:\Users\name\file.txt")    # raw文字列でOK

まとめ

機能 メソッド
パス結合 Path("a") / "b"
ファイル名 .name, .stem, .suffix
親ディレクトリ .parent
存在確認 .exists()
読み書き .read_text(), .write_text()
一覧取得 .iterdir(), .glob(), .rglob()
変換 .with_name(), .with_suffix()
from pathlib import Path

# これだけで始められる
p = Path(".")
for f in p.rglob("*.py"):
    print(f)
9
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?