pathlibが便利すぎてもうos.pathは使えない件
はじめに
こんにちは、@nano_sudoです!
皆さんは、普段何も考えずにos.path
を使っていませんか?
タイトルにもある通り、pathlib
が便利すぎるので、今日はpathlib
をマスターして、os.path
地獄から脱出しましょう!
pathlibとは
pathlib
は、ファイルパスを扱うためのライブラリです。
pathlib
を使うと、ファイルパスを文字列で扱うのではなく、オブジェクトとして扱うことができます。
os.path
じゃだめなの?
pathlib
は、os.path
と比べて、次のようなメリットがあります。
-
豊富なメソッド
pathlib
は、ファイルパスをオブジェクトとして扱うので、ファイルパスに対して様々な操作を行うことができます。 -
パスの区切り文字の違いを吸収してくれる
pathlib
は、OSによって異なるパスの区切り文字を吸収してくれます。
例えば、Windowsでは\
、Linuxでは/
を使いますが、pathlib
を使えば、どちらのOSでも同じコードで動作させることができます。 -
パスの結合が簡単
pathlib
は、/
演算子を使ってパスを結合することができます。
例えば、/
演算子を使って/home/user
と/home/user/test.txt
を結合すると、/home/user/test.txt
となります。
主要なクラス
pythonドキュメントより引用
基本的には、Path
クラスを使うことになりますが、 このクラスが出てきたときに混乱しないように、まずはクラスの構造を理解しておきましょう。
-
PurePath
- システム非依存の一般的なパス操作を提供する基底クラス
- パス文字列の解析、結合、分割などの基本操作を行う
-
PureWindowsPath
-
PurePath
を継承した抽象クラス - Windowsシステム向けの純粋なパス操作を提供
-
-
PurePostixPath
-
PurePath
を継承した抽象クラス - UNIX系システム向けの純粋なパス操作を提供
-
-
Path
- パス操作の中心的なクラス
-
PurePath
を継承し、ファイルシステム操作を追加 - 実行環境のOSに応じて、自動的にWindowsPathまたはPosixPathのインスタンスを生成する
-
WindowsPath
-
Path
を継承したWindows向けのコンクリートクラス - Windowsシステムのパス表記やファイル操作に特化
- 直接インスタンス化することはできない
-
-
PostixPath
-
Path
を継承したUNIX系向けのコンクリートクラス - UNIX系システムのパス表記やファイル操作に特化
- 直接インスタンス化することはできない
-
早速使ってみる
パスの生成
pathlib
は、Path
クラスを使ってパスを生成します。
from pathlib import Path
# 絶対パス
path = Path("/home/user/test.txt")
# 並べて書くと、結合される
path = Path("/home", "user", "test.txt") # /home/user/test.txt
# ただし、絶対パスを2つ以上並べて書くと、先に書いたパスは無視されるので注意
path = Path("/home", "/user", "test.txt") # /user/test.txt
# 相対パス
path = Path("test.txt")
# 現在のディレクトリ
path = Path.cwd()
パスの結合
/
演算子を使ってパスを結合することができます。
(便利すぎて最初見たときは感動しました...)
from pathlib import Path
# Pathオブジェクト + Pathオブジェクト
path = Path("/home/user") / Path("test.txt")
# Pathオブジェクト + 文字列
path = Path("/home/user") / "test.txt"
# joinpathメソッド
path = Path("/home/user").joinpath("test.txt")
# 結合結果
print(path) # /home/user/test.txt
パスの分解
from pathlib import Path
path = Path("/home/user/test.txt")
# ディレクトリ名
print(path.parent) # /home/user
# ファイル名と拡張子
print(path.name) # test.txt
# ファイル名(拡張子なし)
print(path.stem) # test
# 拡張子
print(path.suffix) # .txt
tar_gz = Path("/home/user/test.tar.gz")
# tar.gzなどの複数の拡張子を取得
print(tar_gz.suffixes) # ['.tar', '.gz']
print("".join(tar_gz.suffixes)) # .tar.gz
パスの存在確認
os.path.exists
と同じように、path.exists
でパスの存在確認ができます。
from pathlib import Path
path = Path("/home/user/test.txt")
# パスが存在するか
print(path.exists()) # True
# パスがファイルか
print(path.is_file()) # True
# パスがディレクトリか
print(path.is_dir()) # False
相対パスと絶対パスの変換
Path.relative_to(<相対の基準となるパス>)
で、絶対パスを相対パスに変換することができます。
Path.absolute()
で、相対パスを絶対パスに変換することができます。
Path.resolve()
で、..
や.
を含むパスを解決することができます。
from pathlib import Path
# 絶対パス
abspath = Path("/home/user/test.txt")
# 相対パス化
print(abspath.relative_to("/home")) # user/test.txt
# 相対パス
relpath = Path("user/test.txt")
# 絶対パス化
print(relpath.absolute()) # /home/user/test.txt
# ..や.を含むパスを解決する
print(Path("user/../test.txt").resolve()) # /home/test.txt
パスの操作
pathlib
では、パスに対して様々な操作を行うことができます。
from pathlib import Path
path = Path("/home/user/test.txt")
# パスの移動・名前変更(上書きを行わない)
path.rename("/home/user/test2.txt")
# パスの移動・名前変更(上書きを行う)
path.replace("/home/user/test2.txt")
# パスの作成
path.mkdir() # parents=Trueで親ディレクトリも作成可能
# パスの削除
path.rmdir()
ファイルの操作
pathlib
では、ファイルに対して様々な操作を行うことができます。
from pathlib import Path
path = Path("/home/user/test.txt")
# open()と同じようにファイルを開く
with path.open(encoding="utf-8") as f:
print(f.read())
# ファイルの読み込み
path.read_text()
# ファイルの書き込み
path.write_text("Hello World!")
# ファイルの削除
path.unlink() # ディレクトリの場合はrmdir()
jsonを読み込む例
from pathlib import Path
import json
# ファイルの読み込み
path = Path("/home/user/test.json")
data = json.loads(path.read_text())
# ファイルの書き込み
path.write_text(json.dumps(data))
open()
を使うよりも、pathlib
を使った方が、簡潔に書くことができます。
特に、ファイルを閉じる処理を書く必要がないので、コードが簡潔になります。
情報の取得
from pathlib import Path
fpath = Path("/home/user/test.txt")
# ファイルのサイズ
print(fpath.stat().st_size) # 11
# ファイルの更新日時
print(fpath.stat().st_mtime) # 1620000000.0
# ファイルの作成日時
print(fpath.stat().st_ctime) # 1620000000.0
dpath = Path("/home/user")
# ディレクトリの中身を取得
print(list(dpath.iterdir())) # [PosixPath('/home/user/test.txt')]
# ディレクトリの中身を再帰的に取得
print(list(dpath.glob("**/*"))) # [PosixPath('/home/user/test.txt')]
# ファイルを再帰的に取得
print(list(dpath.glob("**/*.txt"))) # [PosixPath('/home/user/test.txt')]
まとめ
いかがでしたでしょうか?
pathlib
は、複雑なファイル構造を扱うときに、いつも重宝しています。
ぜひ使ってみて、良きPythonライフを送ってください!
間違いや、不明点があれば、コメントまたは、@nano_sudoまでお願いします!
Discussion