Pathlib と os.path の使いやすさを比較してみる
TD;LR
Python はファイルシステムを操作するための 2 つの主要なモジュール pathlib
と os.path
を提供している。
どちらのモジュールも、ファイルやディレクトリの発見、作成、変更、削除を行う機能を提供するが、コードの可読性や理解のしやすさの観点でどちらが扱いやすいかを比較した。
pathlib の方がコードを簡潔に記述できるため、扱いやすいと感じた。
os.path モジュール
os.path モジュールは、Python でファイルパスを操作するためのツールを提供します。主な機能には、ファイルやディレクトリの存在確認(os.path.exists)、絶対パスへの変換(os.path.abspath)、ディレクトリ名やファイル名の分割(os.path.dirname, os.path.basename)、パスの結合(os.path.join)などがあります。これにより、プラットフォーム間の互換性を保ちながら、効率的にファイルシステム操作を行うことができます。
pathlib モジュール
Python 3.4 で導入されたファイルやディレクトリパスをオブジェクト指向で操作するためのツールです。従来の os.path に代わり、パス操作をより直感的に行えるよう設計されています。Path クラスを使って、パスの結合(/演算子)、ファイルの存在確認(.exists())、読み書き(.read_text(), .write_text())などが簡単に行えます。異なる OS 間のパス表記の違いも吸収し、クロスプラットフォームでのファイル操作を容易にします。
注意
pathlib について、Python 3.4 で導入されたため、python2 との互換性について議論されますが、データエンジニアをやっていると、python3.9 以降しか扱ったことがないので、特に互換性については言及しません。
さっそく比較してみる
パスとファイル属性の結合
import os
file_path = os.path.join("../directory", "subdirectory", "file.txt")
file_exists = os.path.isfile(file_path)
parent_folder = os.path.dirname(file_path) # ../directory/subdirectory
file_name = os.path.basename(file_path) # file.txt
extension = os.path.splitext(file_path)[-1] # txt.
from pathlib import Path
file_path = Path("../directory") / "subdirectory" / "file.txt"
file_exists = file_path.is_file()
parent_folder = file_path.parent # ../directory/subdirectory
file_name = file_path.name # file.txt
extension = file_path.suffix # txt.
os.path では、拡張子の取得時に splittext
を使うなど、直感的でない記述になります。
pathlib の方が、ファイル属性への取得が suffix
シンプルに記述できています。
ファイルの読み込み
import os
file_path = os.path.join("directory", "file.txt")
with open(file_path) as file:
content = file.read()
from pathlib import Path
file_path = Path("directory") / "file.txt"
content = file_path.read_text()
os.path では、リソースリークを予防するために、with open()
を使う必要があります。
pathlib の方が、read_text()
を使うことで、シンプルにテキストの取得ができています。
個人的には、コンテキストマネージャーを使わなくても、記述できるのはいいなと思いました。
ディレクトリ内のファイルをリスト化
import os
directory = "directory"
# リスト内包表記を使って、ディレクトリ内のファイルのリストを作成
files = [
os.path.join(directory, f)
for f in os.listdir(directory)
if os.path.isfile(os.path.join(directory, f))
]
# リスト内包表記を使わない場合
for_files = []
for f in os.listdir(directory):
file_path = os.path.join(directory, f)
if os.path.isfile(file_path):
for_files.append(file_path)
from pathlib import Path
directory = Path("some_directory")
files = [f for f in directory.iterdir() if f.is_file()]
os.path のリスト内包表記は冗長になりすぎて内容を理解しにくいです。
内包表記を使わない場合でも、for ループと if を使わねばならず、長くなりがちです。
pathlib であれば、リスト内包表記を簡潔に書けるため理解しやすいです。
新規ディレクトリの作成
import os
dir_path = os.path.join("directory", "to", "new_directory")
os.makedirs(dir_path, exist_ok=True)
from pathlib import Path
dir_path = Path("directory") / "to" / "new_directory"
dir_path.mkdir(parents=True, exist_ok=True)
こちらについては、exist_ok=True ですでにディレクトリが存在する場合でもエラーになりません。
よって、どちらも同じように記述できるため違いはありませんでした。
まとめ
Pathlib は、os.path と比較してコードをより簡潔かつ直感的に記述でき、特にファイルやディレクトリ操作において可読性が高いです。
よく使う定型的なコードをシンプルに書けるため、コード全体がスッキリしそうです。
Discussion