PythonのPathlibモジュールは、ファイルやフォルダーを扱う方法を簡素化します。
Pathlib モジュールは Python 3.4 以降のバージョンで利用可能です。
Pythonのファイルシステムモジュールであるos, os.path, globなどの最良のものを組み合わせています。
Pythonでは、ほとんどのスクリプトがファイルシステムとのやりとりを伴います。
したがって、ファイル名とパスを扱うことは重要です。
このため、PythonにはPathlibモジュールがあり、ファイル関連のタスクを実行するための便利な関数が含まれています。
Pathlibはファイルシステムのパスを適切なオブジェクトとして表現することで、より読みやすく、より簡単にパスを構築する方法を提供し、プラットフォーム間で移植可能なコードを書くことを可能にしています。
この記事では、様々な例を参考にしながら、Pathlib モジュールを詳しく勉強していきます。
パスとディレクトリの概念
Pathlib モジュールの詳細に進む前に、2 つの異なる概念、すなわちパスとディレクトリを理解することが重要です。
パスは、ファイルを識別するために使用されます。
パスは、ファイル名拡張子を含む最終的なファイル名で終端された、ディレクトリ名のオプションのシーケンスを提供します。
ファイル名拡張子は、ファイルのフォーマットやコンテンツに関する情報を提供します。
Pathlib モジュールは、相対パスだけでなく絶対パスも扱うことができます。
絶対パスはルートディレクトリから始まり、完全なディレクトリツリーを指定する。
一方、相対パスはその名が示すように、他のファイルやディレクトリ(通常はカレントディレクトリ)からの相対的なファイルのパスである。
ディレクトリはパスのファイルシステムエントリを表し,ファイル名,作成時間,サイズ,所有者などを含む.
PythonのPathlibモジュールは、ファイル名や他のパスから新しいパスを構築したり、パスの様々なプロパティをチェックしたり、特定のパスにファイルやフォルダを作成するなど、パスに関連するタスクを扱います。
Pathlib モジュールの使用方法
pathlib モジュールをスクリプト内で便利に使うには、その中のすべてのクラスをインポートします。
from pathlib import *
まず、カレントワーキングディレクトリとホームディレクトリのオブジェクトをそれぞれ以下のコードで取得してみましょう。
current_dir = Path.cwd()
home_dir = Path.home()
print(current_dir)
print(home_dir)
すべてのクラスをインポートする代わりに、import pathlib
を選択することができます。
その場合、そのモジュール内でそれ以降に使用するクラスにはすべて pathlib
というプレフィックスを付けなければなりません。
import pathlib
current_dir = pathlib.Path.cwd()
home_dir = pathlib.Path.home()
print(current_dir)
print(home_dir)
Pathlib モジュールを使用する理由
Python 言語をしばらく使っていると、os
, os.path
, glob
などのモジュールがすでにある中で、Pathlib モジュールの必要性は何だろうかと疑問に思うことでしょう。
これは十分に正当な懸念です。
例によって、これを解決してみましょう。
例えば、カレントワーキングディレクトリに “output/output.xlsx” という名前のファイルを作りたいとします。
次のコードは os.path
モジュールを使ってこれを実現しようとするものです。
このとき、os.getcwd
と os.path.join
という関数が使われます。
import os
outpath = os.path.join(os.getcwd(), 'output')
outpath_file = os.path.join(outpath, 'out.xlsx')
別の方法として
outpath_file = os.pathjoin(os.path.join(os.getcwd(), 'output'), "out.xlsx")
このコードは動作はしますが、見た目は不格好で、読みやすくもなく、メンテナンスも容易ではありません。
もし、複数のネストされたディレクトリの中に新しいファイルを作成したい場合、このコードがどのように見えるか想像してみてください。
同じコードをPathlibモジュールを使って書き直すと、以下のようになります。
from pathlib import Path
outpath = Path.cwd() / 'output' / 'output.xlsx'
この形式の方が、精神的に解析しやすい。
Pathlib では、現在の作業ディレクトリを取得するために Path.cwd()
関数を使用し、パスの一部を複合パスオブジェクトに結合するために os.path.join
の代わりに /
演算子を使用します。
また、os.path
モジュールの関数ネストパターンは、Pathlib モジュールの Path
クラスに置き換えられ、メソッドと属性を連結することでパスを表現します。
演算子 /
を巧みにオーバーロードすることで、コードが読みやすくなり、メンテナンスも容易になります。
Pathlib モジュールが提供するメソッドのもう一つの利点は、パスの文字列表現を作成するのではなく、 Path
オブジェクトを作成することです。
このオブジェクトはいくつかの便利なメソッドを持っており、パスを表す生の文字列を扱うよりも簡単に生活をすることができます。
パスに対する操作の実行
古典的な os.path
モジュールは、パスの文字列を操作するためだけに使用されます。
例えば、ディレクトリを作成するなど、パスに対して何らかの操作を行うには、 os
モジュールが必要です。
osモジュールは、ファイルやディレクトリを操作するための一連の関数を提供します。
ディレクトリを作成するmkdirや、ディレクトリの名前を変更する
rename、ディレクトリのサイズを取得する
getsize` などです。
これらの操作を os
モジュールを使って記述し、同じコードを Pathlib モジュールを使って書き換えてみよう。
os` モジュールを使って書かれたサンプルコード
if os.path.isdir(path):
os.rmdir(path)
同じ機能を実現するために、Pathlib モジュールの path
オブジェクトを使用すると、以下のように、より読みやすく、保守しやすいコードになります。
if path.is_dir()
path.rmdir()
パス関連の機能を os
モジュールの中から探すのは面倒です。
Pathlib モジュールは os
モジュールのユーティリティをパスオブジェクトのメソッドに置き換えることで、この問題を解決しています。
この問題を解決するために、Pathlibモジュールが開発されました。
outpath = os.path.join(os.getcwd(), 'output')
outpath_tmp = os.path.join(os.getcwd(), 'output.tmp')
generate_data(output_tmp)
if os.path.getsize(output_tmp):
os.rename(outpath_tmp, outpath)
else: # Nothing produced
os.remove(outpath_tmp)
ここで、関数 generate_data()
はファイルのパスをパラメータとして受け取り、データを別のパスに書き込む。
しかし、パラメータとして渡されたファイルが、最後に generate_data()
関数を実行したときから変更されていない場合、空のファイルが生成されます。
その場合、空のファイルは以前のバージョンのファイルと置き換えられる。
変数 outpath
には、現在の作業ディレクトリとファイル名 “output” を連結してデータを格納する。
同様に、outpath.tmp
という名前のテンポラリバージョンも作成する。
tempバージョンのサイズが0でない場合、つまり空のファイルでない場合は、tempバージョンの名前を outpath
に変更する。
それ以外の場合は、tempバージョンを削除し、古いバージョンを保持する。
osモジュールを使用する場合、ファイルシステムのパスを文字列オブジェクトとして操作すると、
os.path.join()や
os.getcwd()` などの複数の呼び出しが発生し、煩雑になる。
この問題を避けるために、Pathlibモジュールは、パスに対して頻繁に使用される操作を、より読みやすく、シンプルで、オブジェクト指向の方法で使用できるクラス群を提供します。
では、上記のコードをPathlibモジュールを使って書き直してみましょう。
from pathlib import Path
outpath = Path.cwd() / 'output'
outpath_tmp = Path.cwd() / 'output_tmp'
generate_data(output_tmp)
if outpath_tmp.stat().st_size:
outpath_tmp.rename(outpath)
else: # Nothing produced
Path_tmp.unlink()
Pathlibを使うと、os.getcwd()はPath.cwd()になり、パスの結合には’/’オペレータが使われ、os.path.joinの代わりに使われます。
Pathlibモジュールを使用すると、演算子やメソッドコールを使用して、よりシンプルな方法で物事を行うことができます。
以下は,よく使われるメソッドとその使い方です.
-
Path.cwd()
: カレントワーキングディレクトリを表すパスオブジェクトを返す -
Path.home()
: ホームディレクトリを表すパスオブジェクトを返す *Path.home()
: ホームディレクトリを表すパスオブジェクトを返す -
Path.stat()
: パスの情報を返す。 -
Path.chmod()
: ファイルモードとパーミッションを変更する -
Path.glob(pattern)
: *Path.glob(pattern)
: パスが示すディレクトリで与えられたパターンをグロブし、あらゆる種類のファイルにマッチするものを生成する -
Path.mkdir()
: 指定されたパスに新しいディレクトリを作成する -
Path.open()
: パスで作成されたファイルを開く -
Path.rename()
: ファイルやディレクトリの名前を、指定されたターゲットに変更する -
Path.rmdir()
: 空のディレクトリを削除する -
Path.unlink()
: ファイルやシンボリックリンクを削除する
クロスプラットフォームパスの生成
パスは、オペレーティング・システムによって異なる規則が使用されています。
Windows はフォルダ名の間にバックスラッシュを使用しますが、他のすべての一般的なオペレーティングシステムはフォルダ名の間にフォワードスラッシュを使用します。
Python のコードを OS に関係なく動作させたい場合は、プラットフォームごとに異なる慣例を処理する必要があります。
Pathlib モジュールはファイルのパスを簡単に扱えるようにします。
Pathlib では、OS に関係なく、パスやファイル名をスラッシュで Path()
オブジェクトに渡すだけでよいのです。
あとは Pathlib が処理します。
pathlib.Path.home() / 'python' / 'samples' / 'test_me.py'
Path()オブジェクトは、
/を OS に応じた適切なスラッシュに変換します。
Pathlib.Path は Windows または Posix のパスを表現することができます。
このように、Pathlib はパスを簡単に処理することで、多くの機能横断的なバグを解決します。
パス情報の取得
パスを扱うとき、ファイルやフォルダーの親ディレクトリを見つけたり、シンボリックリンクをたどったりすることに関心があります。
パスのさまざまな部分が以下のようなプロパティとして利用できるため、Path クラスはこれを行うためのいくつかの便利なメソッドを備えています。
-
drive
: ドライブ名を表す文字列です。例えば、PureWindowsPath('c:/Program Files/CSV').drive
は “C:” を返します。 -
parts
: パスの構成要素にアクセスするためのタプルを返します。 -
name
: ディレクトリを除いたパスの構成要素 -
parent
: パスの論理的な祖先へのアクセスを提供するシーケンス -
stem
: 最終的なパスの構成要素 (サフィックスを含まない) -
suffix
: 最終的な構成要素のファイル拡張子 -
anchor
: ディレクトリの前にあるパスの部分。/
は子パスを作成するために使用され、os.path.join
の挙動を模倣しています。 -
joinpath
: パスと与えられた引数を結合します。 -
match(pattern)
: 与えられたグロブスタイルのパターンとパスのマッチングを行い、真/偽を返します。
in path “/home/projects/stackabuse/python/sample.md”:
-
path
: – PosixPath(‘/home/projects/stackabuse/python/sample.md’)を返します。 -
path.parts
: – (‘/’, ‘home’, ‘projects’, ‘stackabuse’, ‘python’) を返します。 -
path.name
: – ‘sample.md’ を返します。 -
path.stem
: – ‘sample’を返します。 -
path.suffix
: – ‘.md’を返します。 -
path.parent
: – PosixPath(‘/home/projects/stackabuse/python’)を返します。 -
path.parent.parent
: – PosixPath(‘/home/projects/stackabuse’)を返します。 -
path.match('*.md')
: Trueを返します。 -
PurePosixPath('/python').joinpath('edited_version')
: (‘home/projects/stackabuse/python/edited_version’) を返します。
Globモジュールの代替品
Python には os
や os.path
モジュールの他に、ファイルパスに関連するユーティリティを提供する glob
モジュールも用意されています。
glob モジュールの glob.glob
関数は、パターンにマッチするファイルを検索するために使用されます。
from glob import glob
top_xlsx_files = glob('*.xlsx')
all_xlsx_files = glob('**/*.xlsx', recursive=True)
pathlib も同様にグロブユーティリティを提供する。
from pathlib import Path
top_xlsx_files = Path.cwd().glob('*.xlsx')
all_xlsx_files = Path.cwd().rglob('*.xlsx')
glob の機能は Path
オブジェクトで利用することができます。
このように、pathlib のモジュールは複雑なタスクをよりシンプルにすることができます。
Pathlibを使ったファイルの読み書き
ファイルの読み書きのような基本的な操作を行うには、以下のメソッドを使用します。
-
read_text
: ファイルをテキストモードでオープンし、ファイルの内容を読み込み、読み込んだ後にファイルを閉じる -
read_bytes
: バイナリモードでファイルを開き、バイナリ形式で内容を返し、その後ファイルを閉じる *read_bytes
: ファイルをバイナリモードで開き、バイナリ形式で内容を返し、その後ファイルを閉じる。 -
write_text
: ファイルを開き、テキストを書き込んでから閉じる。 -
write_bytes
: ファイルを開き、テキストを書き込んでから閉じる。バイナリデータをファイルに書き出し、書き出したらファイルを閉じる。
では、一般的なファイル操作に対する Pathlib モジュールの使用法を調べてみましょう。
次の例は、ファイルの内容を読み取るために使用します。
path = pathlib.Path.cwd() / 'Pathlib.md'
path.read_text()
ここでは、Path
オブジェクトの read_text
メソッドを使用して、ファイルの内容を読み込んでいます。
次の例は、ファイルにテキストモードでデータを書き込むために使用します。
from pathlib import Path
p = Path('sample_text_file') p.write_text('Sample to write data to a file')
このように、Pathlib モジュールでは、パスをオブジェクトとして持つことで、ディレクトリの作成や削除、特定のファイルの検索、ファイルの移動など、多くのパス操作を伴うファイルシステム用のオブジェクトに対して便利なアクションを実行することができます。
結論
結論として、Pathlib モジュールは、パスに関連するさまざまな操作を実行するために使用できる、豊富で便利な機能を大量に提供します。
さらに、このライブラリはオペレーティングシステムに関係なく一貫性があります。