Python でファイルパス文字列
Python でファイルパス文字列を扱う方法について。
ファイルからなにかデータを読み込む、あるいはデータを何からの形式で書き出すなど、言語の種類に関わらずファイル操作は重要である。 そのために、ファイルパス文字列を扱う場面は往々にしてあるわけである。
例えば、ディレクトリ名(dirname
)とファイル名(basename
)が別々の変数に入っていて、それらをつなげて絶対ファイルパス文字列を作ろうとする際、初心者の頃は愚直に文字列同士を結合する書き方をしていたものだった:
dirname + '/' + filename
そのせいで、パスのスラッシュ /
がダブったり、あるいは足りなかったりして、エラーを生んでしまうなど…。
そこから多少進歩して、 Python 標準の os.path
モジュールを活用して
os.path.join(dirname, filename)
と書くようになっていたが、よく調べればちゃんとファイルパスを扱う専用の機能が標準搭載されるようになっていたらしい…。
Pathlib
を使おう
公式ドキュメント: https://docs.python.org/ja/3.7/library/pathlib.html
Python 3.4 から標準搭載されるようになった機能らしい。
公式の説明によると
このモジュールはファイルシステムのパスを表すクラスを提供していて、様々なオペレーティングシステムについての適切な意味論をそれらのクラスに持たせています。
ということで、これを使うとファイルパス文字列を、純粋な文字列オブジェクトではなく、ちゃんとした(?)ファイルパスオブジェクト Path
で管理できる。
ざっと性質をまとめると以下:
- ファイルパス文字列を与えることで、ファイルパスオブジェクト
Path
を作ることができる- 正確には OS の種類に応じたそのサブクラス
WindowsPath
/PosixPath
を作る - Windows(
WindowsPath
) か、非 Windows(PosixPath
)か、その OS により決定される - それらの親クラスとして
PurePath
/PureWindowsPath
/PurePosixPath
があり、これらは実際のIO操作は伴わない単純な計算処理だけを担う- つまり posix 環境でファイルパス(文字列)の操作はできるが、ファイルアクセスはできない
- 正確には OS の種類に応じたそのサブクラス
- イミュータブルでハッシュ可能、つまり辞書のキー等にも使える
str()
でキャストすればファイルパス文字列に戻せる- スラッシュ
/
でPath
同士の結合ができる(=os.path.join
) - 親ディレクトリや拡張子抜きなど、様々なプロパティを用意
…便利そう。なぜ今まで知らなかったのか。
以下、対話環境で簡単にテスト
>>> from pathlib import Path
>>> p1 = Path('/etc/')
>>> p1
PosixPath('/etc')
>>> p1.is_dir()
True
>>> p2 = p1 / Path('systemd')
>>> p2
PosixPath('/etc/systemd')
>>> p2.is_dir()
True
>>> p3 = Path('/tmp')
>>> p3
PosixPath('/tmp')
>>> p3.glob('*')
<generator object Path.glob at 0x7f707e742d60>
.glob
からはジェネレーターが返ってくるので、リストとして保持したい場合は list()
で囲う。