いろいろ備忘録日記

主に .NET とか Go とか Flutter とか Python絡みのメモを公開しています。

Pythonメモ-74 (ライブラリメモ - pathlib) (Path, glob, rglob, iterdir)

概要

標準ライブラリのpathlibについてのメモです。

先日、以下の記事を発見。

pbpython.com

とても分かりやすく纏められていたので、ついでに自分のメモも書こうってなりました。

以下、それぞれの関数についての個人メモです。

上記サイトの内容の方がもっとわかりやすいので、ここから下は見る必要ないかもですw

pathlibとは

pathlibモジュールは、python 3.4 で追加されたモジュールです。

11.1. pathlib — オブジェクト指向のファイルシステムパス — Python 3.6.5 ドキュメント

公式ドキュメントには、オブジェクト指向のファイルシステムパス と記載されている通り

パスという概念を抽象的にオブジェクトとして扱えるようにしてくれます。

これまでは、os.path を利用して処理していた部分を pathlibに置き換えて使うことができます。

もちろん、os.pathもあるので、そのままos.path使ってても何の問題もありません。

結構使いやすいので、個人的にはこのpathlibモジュール好きです。

pathlibモジュールの各関数

以下自分のメモコードをそのまま貼り付けていますので、順不同です。

なお、予め以下を実行している状態です。

import itertools as it
import pathlib

from trypython.common.commoncls import SampleBase
from trypython.common.commonfunc import pr, hr

Path インスタンスの作成 (ctor)

        #
        # (1) Path インスタンスの作成
        #
        hr('Path.ctor()')
        tmp_dir = pathlib.Path('/tmp')
        pr('/tmp', tmp_dir)

結果は

----------------Path.ctor()----------------
/tmp=WindowsPath('/tmp')

try-python/pathlib02.py at master · devlights/try-python · GitHub

ファイルやディレクトリの存在確認 (exists)

        #
        # (2) 存在確認は、exists メソッドで行う
        #
        hr('Path.exists()')
        pr('パス (tmp_dir)', str(tmp_dir))
        pr('存在するか (/tmp)', tmp_dir.exists())

結果は

----------------Path.exists()----------------
パス (tmp_dir)='\\tmp'
存在するか (/tmp)=False

try-python/pathlib02.py at master · devlights/try-python · GitHub

パスの結合 ( / )

HOME ディレクトリの取得 (home())

        #
        # (3) パスの結合は、 / で行える
        # (4) HOME ディレクトリの取得は クラスメソッド home を呼び出す
        #
        hr('Path::home() and path concat by "/"')
        home_dir = pathlib.Path.home()
        work_dir = pathlib.Path('work')
        py_dir = pathlib.Path('try-python')

        src_dir = home_dir / work_dir / py_dir

        pr('パス (src_dir)', str(src_dir))
        pr(f'存在するか (src_dir)', src_dir.exists())

結果は

----------------Path::home() and path concat by "/"----------------
パス (src_dir)='C:\\Users\\xxxx\\work\\try-python'
存在するか (src_dir)=True

try-python/pathlib02.py at master · devlights/try-python · GitHub

ファイル一覧取得 (iterdir())

        #
        # (5) Path 内のファイル一覧を取得するには iterdir メソッドを呼び出す
        #     このメソッドは名前の通り イテレータ を返す
        #
        hr('Path.iterdir() and Path.is_dir() and Path.is_file()')
        pr('ファイル一覧 (iterdir)', src_dir.iterdir())
        pr('ファイル一覧 (iterdir)', [x.name for x in src_dir.iterdir()])

結果は

----------------Path.iterdir() and Path.is_dir() and Path.is_file()----------------
ファイル一覧 (iterdir)=<generator object Path.iterdir at 0x00000000069B0E60>
ファイル一覧 (iterdir)=['.git',
 '.gitignore',
 '.idea',
 'environment.yml',
 'LICENSE',
 'README.md',
 'tests',
 'trypython']

try-python/pathlib02.py at master · devlights/try-python · GitHub

ディレクトリかどうかの確認 (is_dir())

        # (6) ファイル名のみ(親ディレクトリを除く)を取得する場合は name プロパティを呼び出す
        hr('Path.iterdir() and Path.is_dir() and Path.is_file()')
        pr('ファイル一覧 (is_dir)', [x.name for x in src_dir.iterdir() if x.is_dir()])

結果は

----------------Path.iterdir() and Path.is_dir() and Path.is_file()----------------
ファイル一覧 (is_dir)=['.git', '.idea', 'tests', 'trypython']

try-python/pathlib02.py at master · devlights/try-python · GitHub

ファイルかどうかの確認 (is_file())

----------------Path.iterdir() and Path.is_dir() and Path.is_file()----------------
pr('ファイル一覧 (is_file)', [x.name for x in src_dir.iterdir() if x.is_file()])

結果は

----------------Path.iterdir() and Path.is_dir() and Path.is_file()----------------
ファイル一覧 (is_file)=['.gitignore', 'environment.yml', 'LICENSE', 'README.md']

try-python/pathlib02.py at master · devlights/try-python · GitHub

カレントディレクトリの取得 (cwd())

        #
        # (8) 現在のカレントディレクトリは、 Path.cwd() クラスメソッドで取得できる。 (os.getcwd() と同じ)
        #
        hr('Path::cwd()')
        pr('カレントディレクトリ (cwd)', pathlib.Path.cwd())

結果は

----------------Path::cwd()----------------
カレントディレクトリ (cwd)=WindowsPath('C:/Users/xxxx/work/try-python/trypython/stdlib')

try-python/pathlib02.py at master · devlights/try-python · GitHub

シェルのように~を展開 (expanduser())

        #
        # (9) シェルのように ~ を展開するには、 expanduser() メソッドを利用する。
        #
        hr('Path.expanduser()')
        pr('~ の展開 (expanduser)', pathlib.Path('~/work').expanduser())

結果は

----------------Path.expanduser()----------------
~ の展開 (expanduser)=WindowsPath('C:/Users/xxxx/work')

try-python/pathlib02.py at master · devlights/try-python · GitHub

        #
        # (10) ディレクトリの作成は mkdir(), 削除は rmdir() メソッドを利用する。
        #      対象がファイルの場合、削除は unlink() メソッドを利用する。
        #
        hr('Path.mkdir() and rmdir()')
        dir1 = src_dir / 'dir1'
        dir1.mkdir()
        pr('存在する (dir1)', dir1.exists())
        dir1.rmdir()
        pr('存在する (dir1)', dir1.exists())

結果は

----------------Path.mkdir() and rmdir()----------------
存在する (dir1)=True
存在する (dir1)=False

try-python/pathlib02.py at master · devlights/try-python · GitHub

ファイルを開く (open())

        #
        # (11) Path は、ファイル操作用の API も備えている。 open メソッドでファイルをそのまま開ける。
        #
        hr('Path.open()')
        readme = src_dir / 'README.md'
        with readme.open(encoding='utf-8') as fp:
            lines = list(fp)
            pr('README', f'{len(lines)} 行')

結果は

----------------Path.open()----------------
README='37 行'

try-python/pathlib02.py at master · devlights/try-python · GitHub

ファイルデータを全取得 (read_bytes(), read_text(), write_bytes(), write_text())

        #
        # (12) 単純にファイルの中身を全取得したい場合だったら, open メソッドを呼ぶ必要はなく
        #      read_bytes() もしくは read_text() メソッドを呼び出せば取得できる。
        #
        # (*) 書き込む場合は、 write_bytes(), write_text() を利用できる
        #
        hr('Path.read_text()')
        all_text = readme.read_text(encoding='utf-8')
        lines = all_text.split('\n')[:-1]
        pr('README (read_text)', f'{len(lines)} 行')

結果は

----------------Path.read_text()----------------
README (read_text)='37 行'

try-python/pathlib02.py at master · devlights/try-python · GitHub

パターンにマッチしたファイルを取得 (glob(), rglob())

        #
        # (13) glob モジュールのように条件にマッチするファイルを抽出したい場合は glob() メソッドを利用する。
        #      glob() は、リストではなくジェネレータを返す。再帰的に抽出する場合は ** を利用する。
        #
        # (*) Path には、 rglob() というメソッドもあるが、これは glob() に ** を指定した場合と同じ動作。
        #
        hr('Path.glob()')
        all_py_files = src_dir.glob('**/*.py')
        top_10_files = it.islice(all_py_files, 10)
        top_10_names = [x.name for x in top_10_files]
        pr('glob (**/*.py)', top_10_names)

        hr('Path.rglob()')
        all_py_files = src_dir.rglob('*.py')
        top_10_files = it.islice(all_py_files, 10)
        top_10_names = [x.name for x in top_10_files]
        pr('rglob (*.py)', top_10_names)

結果は

----------------Path.glob()----------------
glob (**/*.py)=['test_libs.py',
 '__init__.py',
 '__init__.py',
 'closure01.py',
 'cls01.py',
 'cls02.py',
 'cls03.py',
 'comprehension01.py',
 'contextmanager01.py',
 'coroutine01.py']
----------------Path.rglob()----------------
rglob (*.py)=['test_libs.py',
 '__init__.py',
 '__init__.py',
 'closure01.py',
 'cls01.py',
 'cls02.py',
 'cls03.py',
 'comprehension01.py',
 'contextmanager01.py',
 'coroutine01.py']

try-python/pathlib02.py at master · devlights/try-python · GitHub


過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。