Pythonでフォルダやファイルのパス操作を行う際に便利なライブラリとして、従来のos
モジュールと、新しいpathlib
モジュールがあります。
それぞれに特徴があり、同じタスクを達成する方法が少し異なります。
この記事では、ファイルサイズや更新日時などのプロパティから、パス結合や分解といった基本操作について、os
とpathlib
の両方について使い方を紹介しています。
単にファイルやフォルダのパスを操作を知りたい方だけでなく、どちらを選ぶべきか迷わずに使っている方も是非ご一読下さい。
osとpathlibの違い
os モジュール
os
は、Pythonに古くから存在する標準ライブラリで、ファイルやフォルダに関する低レベルな操作を行う機能が豊富に揃っています。os.path
サブモジュールを使えば、パスの結合や分解、ファイルやフォルダの状態確認など、基本的な操作が可能です。
pathlib モジュール
pathlib
は、Python 3.4で導入された比較的新しいモジュールです。ファイルパスをオブジェクトとして扱うことを特徴としており、直感的かつオブジェクト指向的なコードを書くことができます。
どちらを選ぶべき?使用シーンの違い
os
とpathlib
にはそれぞれの強みがあります。プロジェクトの規模やPythonのバージョン、開発スタイルに応じて適切な選択をすることが重要です。
比較項目 | os | pathlib |
---|---|---|
可読性 | シンプルだが、文字列操作が多く冗長になることも。 | オブジェクト指向的で直感的なコードが書ける。 |
互換性 | Python 2系から利用可能でレガシーコードに最適。 | Python 3.4以降で使用可能。 |
柔軟性 | 低レベルな操作に強い。 | クロスプラットフォーム対応が簡単。 |
学習コスト | 基本的な関数が多く、初心者でも扱いやすい。 | 新しい概念(オブジェクト指向)に慣れる必要あり。 |
用途 | レガシーコードやシンプルなスクリプト向け。 | モダンなアプリケーションや大規模開発向け。 osとpathlibの基本概要 |
osとpathlibで用意されているパス操作の一覧
最初に、os
モジュールとpathlib
モジュールで用意されているパス操作について一覧で紹介しておきます。
機能 | os | pathlib |
---|---|---|
パス結合 | os.path.join(path1, path2, ...) | Path(path1).joinpath(path2, ...) |
パス分解 | os.path.split(path) | Path(path).parts |
ファイル名取得 | os.path.basename(path) | Path(path).name |
フォルダ名取得 | os.path.dirname(path) | Path(path).parent |
拡張子取得 | os.path.splitext(path) | Path(path).suffix |
絶対パス化 | os.path.abspath(path) | Path(path).resolve() |
相対パス化 | os.path.relpath(path, start) | Path(path).relative_to(start) |
パス存在確認 | os.path.exists(path) | Path(path).exists() |
フォルダ判定 | os.path.isdir(path) | Path(path).is_dir() |
ファイル判定 | os.path.isfile(path) | Path(path).is_file() |
ファイル/フォルダ情報 | os.stat(path) | Path(path).stat() |
パスの結合
パスの結合は、os
モジュールの join()
、または pathlib
モジュールの joinpath()
を使います。
import os
combined_path = os.path.join('C:/example_folder', 'subfolder/file.txt')
print(combined_path)
from pathlib import Path
combined_path = Path('C:/example_folder').joinpath('subfolder/file.txt')
print(combined_path)
どちらを使っても、以下の結果が得られます。
C:/example_folder/subfolder/file.txt
パスの分解
パスの分割は、os
モジュールの split()
、または pathlib
モジュールの parts
を使います。
split()
は フォルダパスと ファイル名の2つの値を常にタプルで返します。
import os
dirname, filename = os.path.split('C:/example_folder/subfolder/file.txt')
print(dirname)
print(filename)
C:/example_folder/subfolder
file.txt
一方、parts
も同じようにフォルダパスとファイル名は返してくれるものの、フォルダパスはフォルダ単位で分解された結果が返る点が異なります。
from pathlib import Path
parts = Path('C:/example_folder/subfolder/file.txt').parts
print(parts)
以下の様に、ドライブ名、フォルダ名1,フォルダ名2,・・・ファイル名 に分解されて返されます。
('C:\', 'example_folder', 'subfolder', 'file.txt')
ファイル名、フォルダ名、拡張子の取得
os
モジュールはメソッドとして、 pathlib
モジュールはプロパティとしてファイル名、フォルダ名、拡張子を取得できます。
尚、os
モジュールに用意されている splitext()
は、2つの値が返されます。1つ目の値は、指定したパスから拡張子を取り除いた部分、2つ目の値は拡張子が返されるため、下記のサンプルでは1つ目の値を無視し、2つ目の値だけ取得するようにしています。
import os
# osモジュールを用いたファイル名、フォルダ名、拡張子の取得
path = 'C:/example_folder/subfolder/file.txt'
dirname = os.path.dirname(path) # フォルダ名の取得
filename = os.path.basename(path) # ファイル名の取得
_ , extension = os.path.splitext(path) # 戻り値の1つ目を無視し、2つ目(拡張子)を取得
print(f'フォルダ名:{dirname}')
print(f'ファイル名:{filename}')
print(f'拡張子: {extension}')
from pathlib import Path
# pathlib モジュールを用いたファイル名、フォルダ名、拡張子の取得
path = Path('C:/example_folder/subfolder/file.txt')
dirname = path.parent # フォルダ名の取得
filename path.name # ファイル名の取得
extension = path.suffix # 拡張子の取得
print(f'フォルダ名:{dirname}')
print(f'ファイル名:{filename}')
print(f'拡張子: {extension}')
フォルダ名:P:/MyPythonTool/PyTools
ファイル名:test.py
拡張子: .py
絶対パス化と相対パス化
絶対パス化は、カレントフォルダを起点にした相対パスを絶対パスに変換するものです。os
モジュールではpath.abspath()
を、pathlib
モジュールでは resolve()
を使います。
import os
# os モジュールを使って相対パスから絶対パスを取得
absolute_path = os.path.abspath('example_folder/subfolder/file.txt')
print(f"絶対パス: {absolute_path}")
from pathlib import Path
# pathlib モジュールを使って相対パスから絶対パスを取得
absolute_path = Path('example_folder/subfolder/file.txt').resolve()
print(f"絶対パス: {absolute_path}")
絶対パス: C:/Users/username/current_directory/example_folder/subfolder/file.txt
相対パス化は、指定したパスを起点とした相対パスに変換するものです。os
モジュールではpath.relpath()
を、pathlib
モジュールでは relative_to()
を使います。
import os
# os モジュールを使って絶対パスから相対パスを取得(start引数に起点となるパスを指定)
relative_path = os.path.relpath('C:/example_folder/subfolder/file.txt', start='C:/example_folder')
print(f"相対パス: {relative_path}")
from pathlib import Path
# 絶対パスを指定
absolute_path = Path('C:/example_folder/subfolder/file.txt') # 変換したいパス
start_path = Path('C:/example_folder') # 起点となるパス
# pathlib モジュールを使って絶対パスから相対パスを取得
relative_path = absolute_path.relative_to(start_path)
print(f"相対パス: {relative_path}")
相対パス: subfolder/file.txt
パス/ファイル/フォルダの存在確認
指定したパスがファイルかフォルダのどちらかであることを確認したい場合、os
モジュール とpathlib
モジュールの両方に用意されている exists()
を使います。
ファイルとして存在しているか、あるいはフォルダとして存在しているかを確認したい場合、os
モジュール ではisdir()
やisfile()
を、pathlib
モジュールでは is_dir()
やis_file()
を使います。
import os
res = os.path.exists('C:/example_folder') # ファイル又はフォルダの存在確認(True or False)
res = os.path.isdir('C:/example_folder') # フォルダの存在確認(True or False)
res = os.path.isfile('C:/example_folder/file.txt') # ファイルの存在確認(True or False)
from pathlib import Path
res = Path('C:/example_folder').exists() # ファイル又はフォルダの存在確認(True or False)
res = Path('C:/example_folder').is_dir() # フォルダの存在確認(True or False)
res = Path('C:/example_folder/file.txt').is_file() # ファイルの存在確認(True or False)
ファイル/フォルダ情報の取得
os
モジュール、pathlib
モジュール共に stat()
を使って、ファイル/フォルダ情報(タイムスタンプやアクセス権など)を取得します。
どちらのモジュールを使っても、戻り値はos.stat_result
クラスが返されます。このクラスのプロパティを参照することで、個々のファイル情報にアクセスできます。
尚、最終更新日時、作成日、アクセス日時は 1970年1月1日 00:00:00 UTC からの経過秒が返されるため、下記のサンプルでは 'yyyy/mm/dd hh:mm:ss' の形式に変換しています。
import os
import datetime
# ファイルのパスを指定
file_path = 'C:/Windows/notepad.exe'
# osモジュールを使用
stat = os.stat(file_path)
print(f"ファイルサイズ: {stat.st_size} バイト")
print(f"最終更新日時: {datetime.datetime.fromtimestamp(stat.st_mtime).strftime('%Y/%m/%d %H:%M:%S')}")
print(f"作成日時: {datetime.datetime.fromtimestamp(stat.st_ctime).strftime('%Y/%m/%d %H:%M:%S')}")
print(f"最終アクセス日時: {datetime.datetime.fromtimestamp(stat.st_atime).strftime('%Y/%m/%d %H:%M:%S')}")
print(f"所有者(UID): {stat.st_uid}")
print(f"グループ(GID): {stat.st_gid}")
print(f"パーミッション: {oct(stat.st_mode)}")
print(f"デバイスID: {stat.st_dev}")
print(f"ノードID(iノード): {stat.st_ino}")
print(f"ハードリンク数: {stat.st_nlink}")
from pathlib import Path
import datetime
# ファイルのパスを指定
file_path = 'C:/Windows/notepad.exe'
# pathlibモジュールを使用
stat = Path(file_path).stat()
print(f"ファイルサイズ: {stat.st_size} バイト")
print(f"最終更新日時: {datetime.datetime.fromtimestamp(stat.st_mtime).strftime('%Y/%m/%d %H:%M:%S')}")
print(f"作成日時: {datetime.datetime.fromtimestamp(stat.st_ctime).strftime('%Y/%m/%d %H:%M:%S')}")
print(f"最終アクセス日時: {datetime.datetime.fromtimestamp(stat.st_atime).strftime('%Y/%m/%d %H:%M:%S')}")
print(f"所有者(UID): {stat.st_uid}")
print(f"グループ(GID): {stat.st_gid}")
print(f"パーミッション: {oct(stat.st_mode)}")
print(f"デバイスID: {stat.st_dev}")
print(f"ノードID(iノード): {stat.st_ino}")
print(f"ハードリンク数: {stat.st_nlink}")
ファイルサイズ: 360448 バイト
最終更新日時: 2024/05/31 18:11:33
作成日時: 2024/05/31 18:11:33
最終アクセス日時: 2024/11/16 22:46:46
所有者(UID): 0
グループ(GID): 0
パーミッション: 0o100777
デバイスID: 133544273489860000
ノードID(iノード): 562949955076048
ハードリンク数: 3
os.stat_result
クラスのプロパティは次の通りです。
プロパティ | プロパティ | 説明 |
---|---|---|
ファイルサイズ | st_size | ファイルの場合はファイルサイズのバイト数。 フォルダの場合は常に0が返される。 |
最終更新日時 | st_mtime | ファイルやフォルダの最終更新日時 (内容が変更された場合に更新) |
作成日時 | st_ctime | ファイルやフォルダの作成日時 (システムによる変更日時として扱われることが多い) |
アクセス日時 | st_atime | ファイルやフォルダの最終アクセス日時 |
ファイルの種類 | st_mode | ファイルやフォルダの種類をビットマスクで返します。S_IFDIRでフォルダであることを確認 |
所有者(UID) | st_uid | ファイルやフォルダの所有者ユーザーID |
グループ(GID) | st_gid | ファイルやフォルダの所有者グループID |
パーミッション(アクセス権) | st_mode | ファイルやフォルダのパーミッション (rwx形式などでアクセス権を確認) |
デバイスID | st_dev | ファイルやフォルダが存在するデバイスのID |
ノードID(iノード) | st_ino | ファイルやフォルダのiノードID (ファイルシステム内での一意の識別子) |
ハードリンク数 | st_nlink | ファイルやフォルダのハードリンクの数(通常は2) |
まとめ
この記事では、Pythonでフォルダやファイルのパス操作を行う際に便利なライブラリとして、従来のos
モジュールと新しいpathlib
モジュールの違いと使い方について詳しく説明しました。
また、それぞれのモジュールの特徴や利用シーンに応じた選び方を紹介し、具体的なコード例を通じて基本的な操作方法を示しました。
Pythonでパス操作を行う際には、プロジェクトの要件や好みに応じてos
モジュールとpathlib
モジュールを使い分けることができます。
os
モジュールは歴史が長く、シンプルな操作に向いており、pathlib
モジュールはオブジェクト指向的で、より直感的なコードを提供します。
それぞれの強みを活かして、効率的なパス操作を実装してください。
コメント