Python3.4以降ならos.pathはさっさと捨ててpathlibを使うべき

Python3.4でファイルパス操作を行うモジュールとしてpathlibが追加されました。

今までファイルパス操作はos.pathglobを使っていましたが、pathlibを使うとファイルパスの連続操作がとても書きやすくなるので積極的に使うべきです。

pathlibの特徴

pathlibは次のような特徴があります。

  • オブジェクト指向
  • ファイルパス操作機能の統合

オブジェクト指向

今まで使っていたos.pathなどでは独立した関数で機能を提供していました。

これに対してpathlibではPathクラスのメソッドやプロパティとして機能が提供されています。

pathlib
>>> from pathlib import Path
>>> Path('/a/b/c.txt').parent
PosixPath('/a/b')
>>> Path('/a/b/c.txt').parents[1]
PosixPath('/a')
>>> Path('/a/b').joinpath('c/d')
PosixPath('/a/b/c/d')
>>> Path('/a/b') / 'c/d'
PosixPath('/a/b/c/d')

戻り値もstrではなくPathオブジェクトになっています。

ファイルパス操作機能の統合

今まではos.pathだけでなくosglobや組み込み関数のopenなど複数のモジュールにファイル・パス操作の機能が分散していましたが、pathlibでは大部分の機能が統合されています。

pathlibのglob
Path('.').glob('*')
pathlibのopen
Path('a.txt').open('w')

また、Python3.6以降では今まで使っていたモジュールの一部も引数としてstrだけでなくPathオブジェクトを受け取れるように変更されています。

組み込み関数のopen()にPathオブジェクトを渡す
open(Path('a.txt'), 'w')

pathlibを使うメリット

ここまでの説明で「インスタンスを作成する手間が増えただけでは?」と考える人もいると思います。

しかし、pathlibが真価を発揮するのはパスの連続操作をするときです。

例として、あるファイルが格納されているディレクトリの親ディレクトリにhoge.txtというファイルが存在するかチェックする処理を比較してみましょう。

まずはos.pathを使った場合です。

os.path
>>> os.path.exists(os.path.join(os.path.dirname(os.path.dirname('/a/b/c.txt')), 'hoge.txt'))
False

関数呼び出しが入れ子になっていて、一見して何をやっているのかすぐには理解できません。

次にpathlibを使った場合です。

pathlibその1
>>> Path('/a/b/c.txt').parent.parent.joinpath('hoge.txt').exists()
False
pathlibその2
>>> (Path('/a/b/c.txt').parents[1] / 'hoge.txt').exists()
False

左から右へ自然と読めるので、とてもわかりやくすなります。

このようにpathlibではパスの連続操作がとても読みやすく(書きやすく)なります。

pathlibは普及しているのか

自分は実務でpathlibを使ったことはまだありませんし、使われているコードを見たこともありません。

実際のところどの程度使われているのか調べてみました。

Googleトレンド

https://trends.google.co.jp/trends/explore?date=today%205-y&q=python%20os.path,python%20pathlib

python_os_path__python_pathlib_-_調べる_-_Google_トレンド.png

検索数は増えていますがまだos.pathほどではありません。

GitHub

Codeだと日付検索ができなかったのでIssueで確認します。

os.path pathlib
2014 293 77
2015 897 181
2016 826 342
2017 463 448

※2017/07/23時点の件数

着実にpathlibが増えていて、今年はos.pathを抜きそうな勢いです。

Qiita

QiiTrendで確認してみます。

https://qiitrend.herokuapp.com/trend?mode=count&period=4&query=tag%3Apython+os.path&query=tag%3Apython+pathlib&unit=yearly

QiiTrend.png

Qiitaの記事ではpathlibはほぼ使われていないと言っていいレベルです。

GitHubとQiitaの結果から考えると、日本だけ普及が遅れているということでしょうか。

953contribution

普及に関しては既存ライブラリの互換性の問題もあるかもしれませんね。
特にメジャーなパッケージはPython2とPython3両方をサポートしているので。

個人的には気に入ったので積極的につかっていこうかと思ってます。

14contribution

2.7でも使うということであればバックポートのpathlib2を検討するといいかもしれませんね
https://pypi.python.org/pypi/pathlib2/

7363contribution

2.7でも使えるんですね。知りませんでした。

28contribution

@tag1216 組み込みのopenがpath-like objectを受け取れるのはpython3.6が必要ではないでしょうか?
https://docs.python.org/3.5/library/functions.html#open
https://docs.python.org/3.6/library/functions.html#open

7363contribution

@yawara さん、おっしゃる通りで3.6以降で追加されたようです。
本文に3.6以降であることを明記しました。

394contribution

今後は僕もPath()を使うようにします。Pythonの標準ライブラリでメソッドチェーンができるように実装されているクラスはほぼ皆無なので、意外な印象を受けました。メソッドチェーンが普及してほしい派なので歓迎です。パスを文字列で操作するのは煩雑ですから、このクラスの導入は合理的と思います。ただ目的に特化したクラスはほどほどにしないとJavaっぽくなってしまいますね。

7363contribution

言われてみれば確かにPythonではメソッドチェーンで書けないものが多いですね。map/filter/sortedとか。
メソッドチェーンはPythonだと複数行で書きにくいというのが理由の一つかもしれません。

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.