【Python】pathlib is All You Need
はじめに
はじめに,本記事で筆者が使用している環境や必要なライブラリ (任意) についてまとめます.
環境
PC | MacBook Pro (16-inch, 2019) |
---|---|
OS | Monterey |
CPU | 2.3 GHz 8コアIntel Core i9 |
メモリ | 16GB |
Python | 3.9 |
ディレクトリ構成
root
├── assets
│ └── images
│ └── thumbnail.png
│
├── data
│ ├── 0000.png
│ ├── 0001.jpg
│ ├── 0002.png
│ ├── 0003.jpg
│ ...
└── main.py
使用するライブラリ
本記事で用いるライブラリとバージョンをまとめますが,特に気にせず
pip install opencv-python
で問題ないかと思います.今回は任意なのでライブラリはインストールしなくても問題ありません.
pathlibの魅力
ここでは,pathlibの魅力について実際のコードをもとに説明していきたいと思います.
pathlib
と頻繁に比較されるライブラリとしてos.path
があります.そこで2つのライブラリのシェア率を比較してみましょう.
上記のGoogleの検索回数を見てみると2019年頃から,pathlib
がos.path
に比べて多く検索されている (5/2現在では約5倍) ことがわかります.
それではいよいよコードと共に魅力を伝えていきたいと思います.
ディレクトリ・ファイル名や拡張子の取得
pathlibのコード
from pathlib import Path
root = Path("root")
image = root / "assets/images/thumbnail.png"
print(image.parent)
# /root/assets/images
print(image.name)
# thumbnail.png
print(image.stem)
# thumbnail
print(image.suffix)
# png
os.pathのコード
from os import path
images = path.join(root, "assets/images")
image = path.join(images, "thumbnail.png")
print(path.dirname(image))
# /root/assets/images
print(path.basename(image))
# thumbnail.png
print(path.splitext(path.basename(image))[0])
# thumbnail
print(path.splitext(path.basename(image))[-1])
# png
パスの連結
pathlibを用いると,パスの連結を簡単・感覚的に扱うことができます.
その上,Windows,MacOS,Linux等の環境に依存せずに記述することができます.
pathlibのコード
from pathlib import Path
root = Path("root")
data = root / "data"
# PosixPath('/root/data')
os.pathを使ったコード
import os
root = "root"
data = os.path.join(root, "data")
# '/root/data'
ファイルの一括取得
pathlibを用いると,ファイルの一括取得を別のライブラリを用いる必要がなく実現できます.
そろそろこのあたりでpathlib
の魅力が理解できると思います.
pathlibのコード
from pathlib import Path
root = Path("root")
data = root / "data"
images_path = [p for p in data.glob("*") if (p.is_file and p.suffix in ["png", "jpg"])]
""" [PosixPath('/root/data/0000.png'),
PosixPath('/root/data/0001.jpg'),
PosixPath('/root/data/0002.png'),
PosixPath('/root/data/0003.jpg'),
...]
"""
os.pathを使ったコード
from os import path
from glob import glob
root = "root"
data = os.path.join(root, "data")
images_path = [p for p in glob(os.join(data, "*")) if (p.isfile(p) and path.splitext(p)[-1] in ["png", "jpg"])]
pathilbのデメリット
OpenCV
やjson
など,pathlibを一部扱っていないライブラリが存在するため,pathlibを用いるとエラーが起きてしまうことがあります.
cv2.imreadでのエラー
import cv2
from pathlib import Path
images_path = [p for p in data.glob("*") if (p.is_file and p.suffix in ["png", "jpg"])]
for path in images_path:
image = cv2.imread(path) # Error
これを実行すると,TypeError: Can't convert object to 'str' for 'filename'
というエラーが出ます.これを防ぐにはエラー文にも書かれているように,str
にキャストする必要があります.以下のようにキャストをしましょう
import cv2
from pathlib import Path
images_path = [p for p in data.glob("*") if (p.is_file and p.suffix in ["png", "jpg"])]
for path in images_path:
- # image = cv2.imread(path)
+ image = cv2.imread(str(path))
+ image = cv2.imread(path.as_posix())
json.dumpでのエラー
import json
from pathlib import Path
root = Path("root")
data = root / "data"
data_dict = {
"images_path": [p for p in data.glob("*") if (p.is_file and p.suffix in ["png", "jpg"])]
}
with open("path.json", "w") as f:
json.dump(data, f) # Error
これに対処するには3通りの方法があり,
-
default
でキャスト関数を用いる -
cls
でキャストに使用するクラスを用いる
上記を順番に試してみましょう.
defaultでキャスト関数を用いる
import json
from pathlib import Path
root = Path("root")
data = root / "data"
data_dict = {
"images_path": [p for p in data.glob("*") if (p.is_file and p.suffix in ["png", "jpg"])]
}
with open("path.json", "w") as f:
- # json.dump(data, f) # Error
+ json.dump(data, f, default=str)
clsでキャストに使用するクラスを用いる
import json
from pathlib import Path
class JSONEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, Path):
return obj.as_posix()
root = Path("root")
data = root / "data"
data_dict = {
"images_path": [p for p in data.glob("*") if (p.is_file and p.suffix in ["png", "jpg"])]
}
with open("path.json", "w") as f:
- # json.dump(data, f) # Error
+ json.dump(data, f, cls=JSONEncoder)
おわりに
本記事ではpathlib
というライブラリの魅力について,実際のコードを用いながら説明してきました.
本記事で紹介したpathlib
のメソッド等以外にも便利なメソッド等がたくさんあります.是非自分の調べてみましょう.
- OSに依存しないパスの記述ができる
- パスの連結が直感で (
/
) できる - オブジェクト志向なので
glob
などが扱いやすい
まとめると上記の3つが (今思い出せる限りでは) 魅力ということです.
今回紹介しているもの以外にも魅力があれば,是非共有して頂けると嬉しいです!
Discussion