プロジェクト

全般

プロフィール

操作

第11章 ファイルとディレクトリへのアクセス

11.1 ファイルパス操作を直感的に行う pathlib

pathlib モジュールは、I/O を伴わない機能を提供する 純粋パス (pure path) と、I/O を伴う機能を提供する 具象パス (concrete path) を提供する

  • クラス構成

    クラス名 解説 基底クラス
    PurePath 純粋パスクラスの基底クラス なし
    PurePosixPath 非 Windows 向けの純粋パスクラス PurePath
    PureWindowsPath Windows 向けの純粋パスクラス PurePath
    Path 具象パスクラスの基底クラス PurePath
    PosixPath 非 Windows 向けの具象パスクラス Path PurePosixPath
    WindowsPath Windows 向けの具象パスクラス Path PureWindowsPath
  • Path オブジェクト (PurePath, Path) 共通

    • Path オブジェクト (PurePath Path インスタンス) の生成には、PurePath Path文字列または他のPathオブジェクト を渡す
    • 複数の引数を指定した場合は、それらを連結したオブジェクトが生成される
    • PurePath を使ってインスタンス生成するだけで、環境に合わせて PurePosixPath または PureWindowsPath のインスタンスが生成される
      • Path についても同様に、PosixPath WindowsPath が生成される
    • Path オブジェクト同士、Path オブジェクトと文字列は演算子 / が使用可能で、接続されたパスを持つ Path オブジェクトを返す
  • 純粋パスを扱う PurePath

    >>> from pathlib import PurePath, Path
    >>> PurePath("hello.txt")
    PureWindowsPath('hello.txt')
    >>> PurePath("words", "greeting", "hello.txt")  # 複数文字列指定
    PureWindowsPath('words/greeting/hello.txt')
    >>> PurePath(Path("japanese"), "greeting", "ohayo.txt")  # Pathオブジェクト指定
    PureWindowsPath('japanese/greeting/ohayo.txt')
    >>> PurePath()  # 指定無しはカレントディレクトリ
    PureWindowsPath('.')
    
    # 演算子 `/` による接続パスのオブジェクト生成
    >>> p = PurePath("japanese","greeting")
    >>> p
    PureWindowsPath('japanese/greeting')
    >>> p / "konnichiwa.txt"
    PureWindowsPath('japanese/greeting/konnichiwa.txt')
    >>> "all" / p
    PureWindowsPath('all/japanese/greeting')
    >>> q = PurePath("night", "oyasumi.txt")
    >>> q
    PureWindowsPath('night/oyasumi.txt')
    >>> p / q
    PureWindowsPath('japanese/greeting/night/oyasumi.txt')
    
    • PurePath のプロパティ

      プロパティ名 解説 戻り値
      parts パスの各要素のタプル tuple
      drive ドライブを表す文字列
      C: など
      UNC共有名もドライブ扱い
      str
      root ルートを表す文字列
      / \\ など
      str
      anchor ドライブとルートを結合した文字列 str
      parents 上位パスのシーケンス Path オブジェクトのシーケンス
      parent 直接の上位パス Path オブジェクト
      name パス要素の末尾を表す文字列 str
      suffix 末尾の要素の拡張子(ドット含む)
      一番後ろの拡張子のみ
      str
      suffixes 末尾の要素の拡張子リスト list
      stem 末尾の要素から拡張子を除外した文字列
      一番後ろの拡張子のみ除外する
      str
      >>> from pathlib import PurePath, PureWindowsPath
      >>> p = PurePath('/spam/ham/egg.tar.gz')
      >>> p.parts  # 各要素を取得
      ('/', 'spam', 'ham', 'egg.tar.gz')
      >>> wp = PureWindowsPath('c:/Program Files/spam/ham.exe')
      >>> wp.parts
      ('c:\\', 'Program Files', 'spam', 'ham.exe')
      >>> p.drive  # ドライブを取得
      ''
      >>> wp.drive
      'c:'
      >>> p.root  # ルートを取得
      '/'
      >>> wp.root
      '\\'
      >>> wp.anchor  # ドライブとルートを結合した文字列を取得
      'c:\\'
      >>> for parent in p.parents:  # 上位のパスのシーケンスを取得
      ...     parent
      ...
      PurePosixPath('/spam/ham')
      PurePosixPath('/spam')
      PurePosixPath('/')
      >>> p.parent  # 直接の上位のパスを取得
      PurePosixPath('/spam/ham')
      >>> p.name  # 末尾の要素を取得
      'egg.tar.gz'
      >>> p.suffix  # 拡張子を取得
      '.gz'
      >>> p.suffixes  # 拡張子のリストを取得
      ['.tar', '.gz']
      >>> p.stem  # 末尾の要素から拡張子を除いたものを取得
      'egg.tar'
      
    • PurePath のメソッド

      メソッド名 解説 戻り値
      is_absolute() 絶対パスの場合 True bool
      is_relative_to(*other) other に対して相対なら True
      (other がこのパス、またはこのパスの parents 要素と一致すれば True)
      bool
      match(pattern) glob 形式の pattern と一致すれば True bool
      with_name(name) パスの name 部分を引数 name で置換したパス Path オブジェクト
      with_stem(stem) パスの stem 部分を引数 stem で置換したパス Path オブジェクト
      with_suffix(suffix) パスの suffix 部分を引数 suffix で置換したパス Path オブジェクト
      >>> from pathlib import PurePath
      >>> p1 = PurePath('/spam/ham/eggs.txt')
      >>> p2 = PurePath('eggs.txt')
      >>> p1.is_absolute()  # 絶対パスか
      True
      >>> p2.is_absolute()
      False
      >>> p1.is_relative_to('/spam')  # 指定したパスに対して相対か
      True
      >>> p1.is_relative_to('/ham')  # 指定したパスに対して相対か
      False
      >>> p1.match('*.txt')  # パターンに一致するか
      True
      >>> p1.with_name('hoge.txt')  # nameを変更(eggs.txt→hoge.txt)
      PurePosixPath('/spam/ham/hoge.txt')
      >>> p1.with_stem('fuga')  # stemを変更(eggs→fuga)
      PurePosixPath('/spam/ham/fuga.txt')
      >>> p1.with_suffix('.py')  # 拡張子を変更(.txt→.py)
      PurePosixPath('/spam/ham/eggs.py')
      >>> p1.with_suffix('')  # 拡張子を削除
      PurePosixPath('/spam/ham/eggs')
      
  • 具象パスを扱う Path
    具象パスの昨日はファイルシステムにアクセスするため、基本的に OS 状に捜査対象のファイルパスが存在する必要がある

    メソッド名 解説 戻り値
    cwd() クラスメソッド
    現在のディレクトリを表すオブジェクト
    Path オブジェクト
    home() クラスメソッド
    ユーザのホームディレクトリを表すオブジェクト
    Path オブジェクト
    stat() ファイルの各種情報 os.stat_result オブジェクト
    chmod(mode) パスのパーミッションを変更 None
    exists() パスが存在する場合 True bool
    glob(pattern) パスが指すディレクトリ以下で pattern に一致するファイルやディレクトリの一覧を返すジェネレーター ジェネレーター
    (Path オブジェクト)
    is_dir() bool
    is_file() bool
    iterdir() パス直下のファイルやディレクトリの一覧を返すジェネレーター ジェネレーター
    (Path オブジェクト)
    mkdir(mode=0o777, parents=False, exist_ok=False) パスを新しいディレクトリとして作成 None
    open(mode='r', buffering=-1, encoding=None, errors=None, newline=None) 組み込み関数 open() と同様にファイルを開く ファイルオブジェクト
    read_text(encoding=Noen, errors=None) ファイル内容をテキストとして返す str
    rename(target) パスの名前を変更する
    target 文字列または他の Path オブジェクト
    None
    resolve(strict=False) パスを絶対パスにし、シンボリックリンクを解決する Path オブジェクト
    rmdir() パスが指すディレクトリを削除する
    ディレクトリは空の必要がある
    None
    touch(mode=0o666, exist_ok=True) パスのファイルが存在しない場合、作成
    存在する場合、更新日時を現在日時で更新
    None
    unlink(missing_ok=False) パスのファイルを削除する None
    write_text(data, encoding=None, errors=None) ファイルに data を書き込む
    書き込んだ文字数を返す
    int
    >>> from pathlib import Path
    >>> Path.cwd()  # 現在のディレクトリ
    PosixPath('/Users/takanori/spam/ham')
    >>> Path.home()  # ホームディレクトリ
    PosixPath('/Users/takanori')
    >>> p = 'spam.txt'
    >>> p.exists()  # 存在を確認
    True
    >>> p.stat().st_mode  # 状態を取得
    33188
    >>> p.chmod(0o600)  # パーミッションを変更
    >>> p.stat().st_mode
    33152
    >>> p.is_file()  # ファイルかどうか
    True
    >>> with p.open(encoding='utf-8') as f:  # ファイルを開く
    ...     print(f.read())
    ...
    スパムスパムスパム
    >>> p.write_text('ハムハムハム', encoding='utf-8')  # ファイルに書き込み
    6
    >>> p.read_text(encoding='utf-8')  # ファイルから読み込み
    'ハムハムハム'
    >>> p.unlink()  # ファイルを削除
    >>> p.exists()
    False
    >>> p.touch()  # ファイルを作成
    >>> p.resolve()  # 絶対パスを取得
    PosixPath('/Users/takanori/spam/ham/spam.txt')
    
    • glob(), iterdir() での検索例

      ./a.py
      ./b.py
      ./datas
      ./datas/c.txt
      ./datas/d.txt
      ./readme.txt
      
      >>> from pathlib import Path
      >>> p = Path()  # 現在のディレクトリのパスオブジェクトを取得
      >>> p.iterdir()  # iterdir()はジェネレーターを返す
      <generator object Path.iterdir at 0x7f9f300f7740>
      >>> sorted(p.iterdir())  # ディレクトリ直下の全オブジェクトを返す
      [PosixPath('a.py'), PosixPath('b.py'), PosixPath('datas'), PosixPath('readme.txt')]
      >>> list(p.glob('*.txt'))  # *.txtというファイルを返す
      [PosixPath('readme.txt')]
      >>> sorted(p.glob('**/*.txt'))  # ディレクトリを再帰的にたどって*.txtというファイルを返す
      [PosixPath('datas/c.txt'), PosixPath('datas/d.txt'), PosixPath('readme.txt')]
      
  • path-like オブジェクト

    • 以前は Python でのパス使用は、パス文字列での指定だけだったが、現在は Path のような path-like オブジェクト が使用できる

    path-like オブジェクトに対応する関数、標準ライブラリ

    名前 説明
    open() 関数 ファイルを開く組み込み関数
    configparser 設定ファイルのパーサー
    zipfile zip アーカイブファイルの操作
    sqlite3 SQLite データベース
    shutil 高水準ファイル操作
    os OS のインターフェース
    os.path パスの操作

11.2 一時的なファイルやディレクトリを生成する tempfile

作成ユーザのみ読み書き可能なパーミッション、競合しないなど、可能な限り安全なファイル・ディレクトリ生成が行われる

  • 以下の 4 つの呼び出し可能オブジェクトは、コンテキストマネージャーとして with 文で使用可能

    呼び出し可能オブジェクト 解説
    TemporaryFile() ファイル名の無い一時ファイルを作成
    NamedTemporaryFile() ファイル名がある一時ファイルを作成
    SpooledTemporaryFile() 一定サイズまでメモリ上で処理され、超えるとディスク書き出しが行われる一時ファイルを作成
    TemporaryDirectory() 一時ディレクトリを作成
    • TemporaryFile() ファイルシステム上に名前を持ったファイルとして生成される保証はない
    • NamedTemporaryFile() ファイルシステム上に名前を持ったファイルとして生成される為、他システム等から参照可能
    • これらはそれぞれ適切な一時ファイルインスタンスを返すため、インスタンス型は関数名とは必ずしも一致しない
  • 一時ファイルを作成する

    • TemporaryFile(mode='w+b', buffering=-1, encoding=None, newline=None, suffix=None, prefix=None, dir=None, *, errors=None)
      • mode 一時ファイルオープン時のモード
      • buffering バッファリングポリシー
        • 0 バッファリング無し (バイナリのみ)
        • 1 行単位バッファリング (テキスト書き込みのみ)
        • 1より大きい整数 指定値バイトの固定サイズチャンクバッファ
      • encoding 文字エンコード
      • newline
        • None
        • ''
        • \n
        • \r
        • \r\n
      • suffix 文字列指定すると、ファイル名の接尾辞として使用される
      • prefix 文字列指定すると、ファイル名の接頭辞として使用される
      • dir ファイルを生成するディレクトリを指定する
        • デフォルトでは環境変数 TMPDIR などの値が採用される
      • errors エンコード、デコード時のエラーの挙動
        • strict 例外 ValueError を発生させる (None も同じ)
        • ignore
        • replace
        • surrogateescape
        • xmlcharrefreplace
        • backslashreplace
        • namereplace
    • NamedTemporaryFile()
      • (TemporaryFile() と同じ引数あり)
      • delete delete_on_close
        • delete=True かつ delete_on_close=True (デフォルト) : コンテキストマネージャーでの終了時、ファイルの close 時に実ファイルが削除される
        • delete=True かつ delete_on_close=False : コンテキストマネージャーでの終了時 (と file-like オブジェクトが消える際) にのみ実ファイルが削除される
        • delete=False (このとき delete_on_close は無視) : 実ファイルの自動削除無し
    >>> with tempfile.TemporaryFile() as temp:
    ...     print(temp)
    ...     temp.write(b"AAA")
    ...     temp.write(b"BBBB")
    ...     temp.seek(0)
    ...     temp.read()
    ...
    <tempfile._TemporaryFileWrapper object at 0x0000021A34892490>  # 型は "_TemporaryFileWrapper" らしい
    3  # write(b"AAA") の返り値(書き込み文字数)
    4  # write(b"BBBB") の返り値(書き込み文字数)
    0  # seek(0) の返り値(オフセット位置)
    b'AAABBBB'  # read() の返り値
    
  • 一時ディレクトリを作成する

    • TemporaryDirectory(suffix=None, prefix=None, dir=None)
      • suffix 文字列指定すると、ディレクトリ名の接尾辞として使用される
      • prefix 文字列指定すると、ディレクトリ名の接頭辞として使用される
      • dir ディレクトリを生成するディレクトリを指定する
    • コンテキストマネージャーとして実行した場合、as キーワードの引数には ディレクトリパス文字列 が渡される
    • コンテキストマネージャーとして試用しなかった場合は TemporaryDirectory インスタンスが返されるが、自分で削除しないといけない...
      • pathlib.Path などで操作

11.3 高レベルなファイル操作を行う shutil

ディレクトリ、ファイル、およびアーカイブに対して高水準な操作を提供する

  • ファイルをコピーする

    関数名 解説 戻り値
    copyfile(src, dst, *, follow_symlinks=True) ファイル src をファイル dst にコピーする str
    copymode(src, dst, *, follow_symlinks=True) パーミッションを src から dst にコピーする None
    copystat(src, dst, *, follow_symlinks=True) パーミッション、最終アクセス時刻、最終変更時刻やその他のファイル情報を src から dst にコピーする None
    copy(src, dst, *, follow_symlinks=True) copyfile() + copymode() str
    (src, dst, *, follow_symlinks=True) copyfile() + copystat() str
    • 引数の src dst にはファイルを表す文字列の他、path-like オブジェクトPath オブジェクト も指定可能
    • copyfile() copy() copy2() の戻り値は dst のパス文字列
    • copy() copy2()dst にはディレクトリを指定可能だが、copyfile() はファイルのみ
    >>> shutil.copyfile("testsrc.txt", "testdst.txt")
    'testdst.txt'
    >>> shutil.copy("testsrc.txt", "testdst_copy.txt")
    'testdst_copy.txt'
    >>> shutil.copy2("testsrc.txt", "testdst_copy2.txt")
    'testdst_copy2.txt'
    
    green@cucumber MINGW64 /e/PythonExamPrac/chapter11
    $ stat ./testsrc.txt
      File: ./testsrc.txt
      Size: 41              Blocks: 1          IO Block: 65536  regular file
    Device: e2ca7b4dh/3804920653d   Inode: 1970324837509872  Links: 1
    Access: (0644/-rw-r--r--)  Uid: (197610/   green)   Gid: (197610/ UNKNOWN)
    Access: 2025-07-23 21:56:51.628029400 +0900
    Modify: 2025-07-23 21:49:51.453832500 +0900
    Change: 2025-07-23 21:49:51.453832500 +0900
     Birth: 2025-07-23 21:49:08.805897000 +0900
    
    green@cucumber MINGW64 /e/PythonExamPrac/chapter11
    $ stat ./testdst.txt
      File: ./testdst.txt
      Size: 41              Blocks: 1          IO Block: 65536  regular file
    Device: e2ca7b4dh/3804920653d   Inode: 281474977245937  Links: 1
    Access: (0644/-rw-r--r--)  Uid: (197610/   green)   Gid: (197610/ UNKNOWN)
    Access: 2025-07-23 21:57:01.835098500 +0900
    Modify: 2025-07-23 21:54:58.789202300 +0900
    Change: 2025-07-23 21:55:04.887191200 +0900
     Birth: 2025-07-23 21:54:58.789202300 +0900
    
    green@cucumber MINGW64 /e/PythonExamPrac/chapter11
    $ stat ./testdst_copy.txt
      File: ./testdst_copy.txt
      Size: 41              Blocks: 1          IO Block: 65536  regular file
    Device: e2ca7b4dh/3804920653d   Inode: 281474977245938  Links: 1
    Access: (0644/-rw-r--r--)  Uid: (197610/   green)   Gid: (197610/ UNKNOWN)
    Access: 2025-07-23 21:56:37.277060300 +0900
    Modify: 2025-07-23 21:55:52.996307000 +0900
    Change: 2025-07-23 21:55:52.996307000 +0900
     Birth: 2025-07-23 21:55:52.996307000 +0900
    
    green@cucumber MINGW64 /e/PythonExamPrac/chapter11
    $ stat ./testdst_copy2.txt
      File: ./testdst_copy2.txt
      Size: 41              Blocks: 1          IO Block: 65536  regular file
    Device: e2ca7b4dh/3804920653d   Inode: 281474977245939  Links: 1
    Access: (0644/-rw-r--r--)  Uid: (197610/   green)   Gid: (197610/ UNKNOWN)
    Access: 2025-07-23 21:56:37.277060300 +0900
    Modify: 2025-07-23 21:49:51.453832500 +0900
    Change: 2025-07-23 21:49:51.453832500 +0900
     Birth: 2025-07-23 21:56:32.456361500 +0900
    
  • 再帰的にディレクトリやファイルを操作する

    関数名 解説 戻り値
    rmtree(path, ignore_errors=False, onerror=None) path で指定したディレクトリを再帰的に削除
    配下のファイル、ディレクトリもすべて削除
    None
    move(src, dst, copy_function=copy2) src ディレクトリ以下のファイルを再帰的に dst に移動
    コピーに使用する関数を指定可能
    str
    • 再帰コピーには copytree() を使用
      • copytree(src, dst, symlinks=False, ignore=None, coy_function=copy2, ignore_dangling_symlinks=False, dirs_exist_ok=False)

        • src コピー対象ディレクトリ
        • dst コピー先ディレクトリ (すでに存在する場合は例外送出)
        • symlinks シンボリックリンクの扱い
          • True : シンボリックファイルのままコピー
          • False : リンク先のファイルをコピーして配置
        • ignore コピー対象外ファイルを決定する関数を指定
          • shutil.ignore_patterns() を利用すると任意パターンのフィルタが利用できる
        • copy_function コピーに用いる関数を指定
        • ignore_dangling_symlinks True にすると、引数 symlinks=False の場合にリンク先が存在しなくてもエラーを出さない
        • dirs_exist_ok True にすると、コピー先ディレクトリが存在していてもエラーを出さない
      • 戻り値 コピー先ディレクトリ名

        $ ls ./from
        a.pyc  a.swp  a.txt  b.txt  c.txt  d.txt
        
        >>> import shutil
        >>> ignore = shutil.ignore_patterns('*.pyc', '*.swp')  # 拡張子が.pycと.swpを除外対象にする
        >>> ignore  # ignore(path, names)という呼び出し可能オブジェクト
        <function ignore_patterns.<locals>._ignore_patterns at 0x7fe7d821aa60>
        >>> shutil.copytree('./from', './to', ignore=ignore)  # fromからtoに再帰的にコピー
        'to'
        
        $ ls ./to
        a.txt  b.txt  c.txt  d.txt
        

Tatsuya ISHIGAKI さんが5ヶ月前に更新 · 1件の履歴