Warning: Undefined variable $position in /home/pystyles/pystyle.info/public_html/wp/wp-content/themes/lionblog/functions.php on line 4897

Python – pathlib を使ったファイルパス操作の使い方

Python – pathlib を使ったファイルパス操作の使い方

概要

Python の新しいファイルパス操作モジュール pathlib の使い方について解説します。 pathlib は Python 3.6 で導入されたファイルパス操作モジュールです。これまでの os.path モジュールに比べて、簡潔にコードが書けるので、Python 3.6 以上であれば、こちらを使用することをおすすめします。

Advertisement

os.path と pathlib

機能的にはどちらも同じことができますが、os.path はファイルパスを表す文字列を扱うのに対し、pathlib はファイルパスをオブジェクト化して扱うという違いがあります。実際の例を見てみましょう。

下記のようなディレクトリ構造があり、A/a.png があるディレクトリを基点に、B/b.png を相対的に指定するコードを考えます。

├── A
│   └── a.png
└── B
    └── b.png
In [ ]:
import os
from pathlib import Path

path = "A/a.png"

# os.path
dst_path = os.path.join(os.path.dirname(os.path.dirname(path)), "B/b.png")
print(dst_path)

# pathlib
dst_path = Path(path).parent.parent / "B/b.png"
print(dst_path)

os.path と比較して、pathlib は簡潔なコードになっていることがわかります。

ファイルの結合

pathlib の一番の特徴はファイルの結合をディレクトリの区切り文字と同じフォワードスラッシュ / で行えることでしょう。

In [ ]:
from pathlib import Path

path = Path("/hoge")

img_path = path / "fuga" / "sample.jpg"
print(img_path)  # /hoge/fuga/sample.jpg

ファイル名や親ディレクトリの取得

パスからファイル名や親ディレクトリなどを取得する方法について紹介します。

Windows Linux
概要 パス C:\data\hoge\sample.tar.gz /data/hoge/sample.tar.gz
パスの構成要素 Path.parts (‘C:\’, ‘data’, ‘hoge’, ‘sample.tar.gz’) (‘/’, ‘data’, ‘hoge’, ‘sample.tar.gz’)
ドライブレター Path.drive C:
ルート Path.root \ /
ドライブレター付きのルート Path.anchor C:\
親ディレクトリの一覧 Path.parents [‘C:/data/hoge’, ‘C:/data’, ‘C:/’] [‘/data/hoge’, ‘/data’, ‘/’]
1つ上の階層 Path.parents[0] C:\data\hoge /data/hoge
2つ上の階層 Path.parents[1] C:\data /data
1つ上の階層 Path.parent C:\data\hoge /data/hoge
ファイル名 Path.name sample.tar.gz sample.tar.gz
拡張子を除いたファイル名 Path.stem sample.tar sample.tar
拡張子 Path.suffix .gz .gz
拡張子の一覧 Path.suffixes [‘.tar’, ‘.gz’] [‘.tar’, ‘.gz’]
ファイル URI で表したパス Path.as_uri() file:///C:/data/hoge/sample.tar.gz file:///data/hoge/sample.tar.gz
\ を / に置き換えたパス Path.as_posix() :/data/hoge/sample.tar.gz

Windows

In [ ]:
from pathlib import Path

path = Path(r"C:\data\hoge\sample.tar.gz")

# パスを分解する
print(path.parts)  # ('C:\\', 'data', 'hoge', 'sample.tar.gz')

# ドライブレターを取得 (Windows)
print(path.drive)  # C:

# ルートを取得
print(path.root)  # \

# ドライブレターとルートを結合した文字を取得 (Windows)
print(path.anchor)  # C:\

# 親ディレクトリの一覧
print([x for x in path.parents])
# [WindowsPath('C:/data/hoge'), WindowsPath('C:/data'), WindowsPath('C:/')]

# 1つ上の階層
print(path.parents[0])  # C:\data\hoge
# 2つ上の階層
print(path.parents[1])  # C:\data

# 1つ上の階層
print(path.parent)  # C:\data\hoge

# ファイル名
print(path.name)  # sample.tar.gz

# 拡張子を除いたファイル名
print(path.stem)  # sample.tar

# 拡張子
print(path.suffix)  # .gz

# 拡張子の一覧
print(path.suffixes)  # ['.tar', '.gz']

# ファイル URI で表したパス
print(path.as_uri())  # file:///C:/data/hoge/sample.tar.gz

# バックスラッシュ \ をフォワードスラッシュ / に置き換えたパス (Windows)
print(path.as_posix())  # :/data/hoge/sample.tar.gz
Advertisement

Unix

In [ ]:
from pathlib import Path

path = Path(r"/data/hoge/sample.tar.gz")

# パスを分解する
print(path.parts)  # ('/', 'data', 'hoge', 'sample.tar.gz')

# ルートを取得
print(path.root) # /

# 親ディレクトリの一覧
print([x for x in path.parents])
# [PosixPath('/data/hoge'), PosixPath('/data'), PosixPath('/')]

# 1つ上の階層
print(path.parents[0])  # /data/hoge
# 2つ上の階層
print(path.parents[1])  # /data

# 1つ上の階層
print(path.parent)  # /data/hoge

# ファイル名
print(path.name)  # sample.tar.gz

# 拡張子を除いたファイル名
print(path.stem)  # sample.tar

# 拡張子
print(path.suffix)  # .gz

# 拡張子の一覧
print(path.suffixes)  # ['.tar', '.gz']

# ファイル URI で表したパス
print(path.as_uri())  # file:///data/hoge/sample.tar.gz

ファイルの存在確認

概要 パス 備考
ファイルが存在するかどうか Path.exists()
ディレクトリかどうか Path.is_dir()
ファイルかどうか Path.is_file()
マウントポイントかどうか Path.is_mount() Unix のみ
シンボリックリンクかどうか Path.is_symlink()
Unix ソケットかどうか Path.is_socket() Unix のみ
ファイルが空かどうか Path.stat().st_size == 0
絶対パスかどうか Path.is_absolute()
パスが other を基点とした相対パスかどうかを判定する PurePath.is_relative_to(*other)
2つのパスが同じ場所を指すかどうか Path.samefile(other_path)

ファイルサイズ、所有ユーザー、所有グループを取得する

以下の関数でファイルサイズ、所有ユーザー、所有グループを取得できます。

In [ ]:
from pathlib import Path

path = Path("sample.jpg")

# ファイルサイズ
print(path.stat().st_size)  # 18122

# ファイルが空かどうか
print(path.stat().st_size == 0)  # False

# ファイルの所有ユーザー
print(path.owner())  # root

# ファイルの所有グループ
print(path.group())  # root

パスの書き換え置き換える

以下の関数でパスからファイル名のファイル名、拡張子を除いたファイル名、拡張子だけを置き換えられます。

In [ ]:
from pathlib import Path

path = Path("hoge/sample.png")

# ファイル名を置き換える
print(path.with_name("fuga.txt"))  # hoge/fuga.txt

# 拡張子を除いたファイル名を置き換える
print(path.with_stem("fuga"))  # hoge/fuga.txt

# 拡張子を除いたファイル名を置き換える
print(path.with_suffix(".jpg"))  # hoge/sample.jpg

# 絶対パスに変換する。
print(path.resolve())  # /data/notebook/pystyle/python/python-pathlib/hoge/sample.png

# シンボリックリンクが指す先を取得する
path = Path("hoge/samples")
print(path.readlink())  # /data/samples
Advertisement

カレントディレクトリ、ホームディレクトリを取得する

概要
カレントディレクトリ Path.cwd()
ホームディレクトリ Path.home()
ホームディレクトリを表す ~ を展開する Path.expanduser()
In [ ]:
# ホームディレクトリを取得する
print(Path.home())  # /root

# カレントディレクトリを取得する
print(Path.cwd())  # /data/notebook/pystyle/python/python-pathlib

# ホームディレクトリを表す ~ を展開する
path = Path("~/sample")
print(path.expanduser())  # /root/sample

権限の変更、ファイル/ディレクトリの作成、削除

mkdir() でディレクトリを作成します。

  • 権限は mode で指定します。ox666 のように8進数で指定するとよいでしょう。
  • parents=True を指定すると、親ディレクトリが存在しない場合はそれも作成します。
  • ディレクトリがすでに存在する場合はデフォルトではエラーになりますが、exist_ok=True を指定すると、ディレクトリが存在しない場合のみ作成します。
In [ ]:
# ディレクトリを作成する。
path = Path("output")
path.mkdir(mode=0o777, parents=True, exist_ok=True)

rmdir() で空のディレクトリを削除できます。

In [ ]:
path = Path("output")
path.rmdir()

中身があるディレクトリでファイルごと削除する場合は shutil.rmtree() を使用します。

権限の変更は chmod() でできます。

In [ ]:
# 権限を変更する。
path = Path("sample.py")
path.chmod(0o666)

touch() で空のファイルを作成します。

  • 権限は mode で指定します。ox666 のように8進数で指定するとよいでしょう。
  • ファイルがすでに存在する場合はデフォルトではエラーになりますが、exist_ok=True を指定すると、ファイルが存在しない場合のみ作成します。
In [ ]:
## ファイルを作成する。
path = Path("sample.txt")
path.touch(mode=0o666, exist_ok=True)

unlink() でファイルを削除します。

  • ファイルが存在しない場合はデフォルトではエラーになりますが、missing_ok=True を指定すると、ファイルが存在する場合のみ削除します。
In [ ]:
# ファイルを削除する。
path = Path("sample.txt")
path.unlink(missing_ok=True)

write_bytes() でバイナリデータ、write_text() でテキストデータをファイルを開いて書き込めます。

In [ ]:
# ファイルを開いて、バイナリデータを書き込む
path = Path("sample.bin")
path.write_bytes(b"Binary file contents")

# ファイルを開いて、バイナリデータを書き込む
path = Path("sample.txt")
path.write_text("Binary file contents")

symlink_to(target)target へのシンボリックリンクを作成します。 Windows の場合、リンク先がディレクトリの場合 symlink_to(target, target_is_directory=True) とする必要があります。

In [ ]:
# シンボリックリンクを作成する。
path = Path("samples")
path.symlink_to("/data/samples")

ファイルを読み込む

Path.read_bytes() で指定したファイルをバイナリモード、Path.read_text() でテキストモードで読み込み、返します。 Path.open() で組み込み関数 open() と同様のファイルオープン処理が行えます。

In [ ]:
path = Path("sample.bin")
print(path.read_bytes())

path = Path("sample.txt")
print(path.read_text())

path = Path("sample.txt")
f = path.open()
print(f.read())

ファイルを移動する、リネームする

Path.rename() でリネーム処理が行えます。

In [ ]:
src = Path("sample.bin")
dst = Path("hoge.bin")
src.rename(dst)
Advertisement

ファイル一覧を取得する

Path.iterdir() でディレクトリ内のファイル一覧を取得できます。 Path.glob()glob.glob() と同様、ワイルドカードを使ったより高度な検索が行えます。glob() で検索する場合、入れ子になったディレクトリも再帰的に検索する場合はその部分を ** にします。

In [ ]:
path = Path("/data")
for p in path.iterdir():
    print(p)
print()

for p in path.glob("*.zip"):
    print(p)
print()

for p in path.glob("**/*.jpg"):  # または path.rglob("*.jpg")
    print(p)
print()