環境
- Windows 10
- Python 3.10.1
- VSCode
ディレクトリ・ファイルパスを扱うことができるモジュール
3種類もあります
- os.path
- glob
- pathlib
個人的には、パスをオブジェクト指向で扱うpathlibがおすすめです。pathlibの使用には、python3.4以上が必要になります
前提知識
- MacなどのUnix系OSでは/から始まり、Windowsではドライブ文字や\\から始まります
- 絶対パスはルートディレクトリからのパス
Windowsであれば「C:¥」や「D:¥」、macやLinuxは「/」がルート - 相対パスは現在位置を起点としたパス
pathlibの使い方
path文字列からpathオブジェクトを生成する
pathlibでは、以下のようにpathオブジェクトを生成するところから始まります
import pathlib
path = pathlib.Path("/var/www/html") # WindowsPath('/var/www/html')
pathオブジェクトは、以下のようにstr()にパラメータとして渡してあげることで、パス文字列に変換することが可能です
import pathlib
path = pathlib.Path("/var/www/html")
path_str = str(path) # '\\var\\www\\html'
内部的には、osによって異なるpathオブジェクトが生成されます
- windowsならWindowsPath
- macならPosixPath
pathlibを使うことにより、Pathオブジェクト生成時のパラメータとして渡すパス文字列は相対パスでも絶対パスでもよく、なおかつパスの記載方法もOSに依存していないため、上記のようにwindowsでもパスを扱うことができています
現在の作業ディレクトリの絶対パスを取得する
cwd()を使用することでカレントワーキングディレクトリの絶対パスを取得できます
import pathlib
path = pathlib.Path.cwd()
path_str = str(path) # 'C:\\Users\\・・・'
実際に存在するパスかチェックする
exists()を使用するとことで、存在する場合はTrueが存在しない場合はFalseが返ります
import pathlib
exsits = pathlib.Path.cwd().exists() # True
絶対パスかどうかチェックする
import pathlib
exsits = pathlib.Path.cwd().is_absolute() # True
相対パスかどうかチェックする
こちらはメソッドがありません・・・
絶対パスを相対パスに変換
relative_to(起点となるパス文字列)とすることで、もともとの絶対パスから基底パスを除いた相対パスとして変換することが可能です
import pathlib
abs_path = pathlib.Path("/var/www/html")
relative_path = abs_path.relative_to("/var") # www/html
相対パスを絶対パスに変換
resolve()を使用することで、相対パスを絶対パスに変換することが可能です
import pathlib
relative_path = pathlib.Path("hoge")
abs_path = relative_path.resolve()
path_str = str(abs_path)
この絶対パスは、cwdに元の相対パスを結合した結果になります
パス文字列の追加(結合)
パスオブジェクトに対して、joinpath()を使用することでパスを追加できます
import pathlib
path = pathlib.Path("hoge").joinpath("foo.txt")
path_str = str(path) # 'hoge\\foo.txt'
パスがディレクトリか、ファイルかをチェックする
import pathlib
is_file = pathlib.Path("hoge").is_file() # False
is_dir = pathlib.Path("hoge").is_dir() # True
ただし、存在しないパスを渡した場合は固定でFalseが返るのでその点だけ注意が必要です
パスを扱う自作クラス
パスの処理に限ったことではないですが、こういうのは専用のクラスを用意するのが吉なので、上記のような基本的な処理をメソッドとして備えた以下のようなクラスを作成しています
shared\Domain\x_file_system_path.py
import pathlib
from shared.Domain.xstr import XStr
class XFileSystemPath:
def __init__(self, path_str: XStr):
# 引数で受け取ったパス文字列(絶対・相対どちらでもOK)からパスオブジェクトを生成
self._path = pathlib.Path(path_str.get_string())
def path(self) -> pathlib.Path:
return self._path
def of_text(self) -> str:
return str(self.path())
# 相対パス(cwdを起点とする相対パス)
# Ex) #'tests\\x_file_system_path.py'
def to_relative(self, base_path=None):
if base_path is None:
base_path = self.path().cwd()
try:
return XFileSystemPath(
XStr(str(self.to_absolute().path().relative_to(base_path)))
)
except:
# 相対パスに変換しようとしたパスに、起点となるcwdが含まれていない場合例外(つまり、もとの絶対パスに起点となるcwdが含まれている必要がある)
raise ValueError
# 絶対パス(cwd + self.path())
# Ex) #'C:\\Users\\・・・\\tests\\x_file_system_path.py'
def to_absolute(self):
return XFileSystemPath(XStr(str(self.path().resolve())))
# 現在の作業ディレクトリ(カレントワーキングディレクトリ)の絶対パス
@staticmethod
def cwd():
return XFileSystemPath(XStr(str(pathlib.Path.cwd())))
# ユーザーのホームディレクトリの絶対パス
# Ex) 'C:\\Users\\nishigaki'
@staticmethod
def home_dir():
return XFileSystemPath(XStr(str(pathlib.Path.home())))
def exsits(self):
return self.path().exists()
# 相対パスかを判定するメソッドはpathilibにはなし
def is_absolute(self) -> bool:
return self.path().is_absolute()
# ディレクトリかどうかを返します
# 存在しないパスは強制的にFalse
def is_file(self) -> bool:
return self.path().is_file()
# ファイルかどうかを返します
# 存在しないパスは強制的にFalse
def is_dir(self) -> bool:
return self.path().is_dir()
# パス文字列を追加して返します
def join(self, *more_path_strs: str):
joined_path_str = str(self.path().joinpath(*more_path_strs))
return XFileSystemPath(XStr(joined_path_str))
本記事とは直接関係はないですが、joinメソッドの引数は可変長にしています。理由は追加したいパス文字列の数を呼び出し側から指定したいためです
Pythonでは、リストや辞書に*をつけると、それらを展開して引数として受け取ることが可能です。これを可変長引数といいます
また、pathlib.Path.home()を使用すると、homeディレクトリを取得することが可能です。
- windows
'C:\\Users\\username' - mac(Ubuntu)
'/home/username'
まとめ
いかがでしたでしょうか。本記事では、PythonでOSに依存せずディレクトリやファイルのパスを扱う方法について紹介しています。windowsとmac(やlinux)ではパス文字列の書き方に差異があるため、何かしらのモジュールを使用しない場合はosに依存してしまいます。pathlibを使用してosに依存しないパスの管理がおすすめです