Python, pathlibでファイルの作成・open・読み書き・削除
Pythonのpathlibモジュールを使ってファイルを新規作成したり読み込み・書き込みを行ったり削除したりする方法について説明する。
pathlibのPath
オブジェクトにはopen()
メソッドがあり、組み込み関数open()
と同様の処理が可能。また、テキストファイルやバイナリファイル全体を読み書きするread_text()
, write_text()
, read_bytes()
, write_bytes()
という便利なメソッドもある。
組み込み関数open()
についての詳細は以下の記事を参照。
pathlibの基礎、ディレクトリの処理については以下の記事を参照。
本記事のサンプルコードでは以下のようにpathlibモジュールからPath
クラスをインポートしている。pathlibは標準ライブラリに含まれているので追加のインストールは不要。
from pathlib import Path
空のファイルを作成、既存ファイルの日時更新: touch()
空のファイルを作成するにはPath
オブジェクトのtouch()
メソッドを使う。
Path()
でPath
オブジェクトを生成する。ここではディレクトリを作成し、その中の新たなファイルのパスを指定する。
Path('temp').mkdir()
p_empty = Path('temp/empty_file.txt')
print(p_empty)
# temp/empty_file.txt
print(type(p_empty))
# <class 'pathlib.PosixPath'>
OSによってPosixPath
またはWindowsPath
のインスタンスが生成される。Path
の基本については以下の記事を参照。
この時点ではファイルは存在していない。exists()
で確認。
print(p_empty.exists())
# False
touch()
で空のファイルが新規作成される。
p_empty.touch()
print(p_empty.exists())
# True
デフォルトでは既存のファイルに対してtouch()
を実行するとタイムスタンプが更新される。Unixのtouch
コマンドと同じ動作。
p_empty.touch()
引数exist_ok
をFalse
とすると既存のファイルに対してはエラーとなる。
# p_empty.touch(exist_ok=False)
# FileExistsError: [Errno 17] File exists: 'temp/empty_file.txt'
新規ファイルを作成する場合は直上のディレクトリまでは作成しておく必要がある。中間ディレクトリが存在しないとエラー。
p_empty_new_dir = Path('temp/new_dir/empty_file.txt')
# p_empty_new_dir.touch()
# FileNotFoundError: [Errno 2] No such file or directory: 'temp/new_dir/empty_file.txt'
中間ディレクトリが存在していない場合は、親ディレクトリのPath
オブジェクトをparent
属性で取得してmkdir()
でディレクトリを作成してからtouch()
を実行する。
p_empty_new_dir.parent.mkdir(parents=True, exist_ok=True)
p_empty_new_dir.touch()
直上のディレクトリまで存在している場合は以下のように一行で書ける。
Path('temp/empty_file2.txt').touch()
ファイルのopen: open()
Path
オブジェクトのopen()
メソッドで、Path
オブジェクトが指すファイルに対して組み込み関数open()
と同じ処理が可能。
引数mode
を'w'
とすると書き込みモード。存在しないファイルを指すパスでは新規作成となる。
p_new = Path('temp/new_file.txt')
print(p_new.exists())
# False
with p_new.open(mode='w') as f:
f.write('line 1\nline 2\nline 3')
引数mode
を'r'
とすると読み込みモード。デフォルトがmode='r'
なので省略可能。
with p_new.open() as f:
print(f.read())
# line 1
# line 2
# line 3
openしたあとの処理はPath
のopen()
メソッドも組み込み関数open()
と同じ。
ファイルオブジェクトのwrite()
やread()
, writelines()
, readlines()
メソッドや追記モードなどの詳細は、組み込み関数open()
についての以下の記事を参照。
テキストファイルやバイナリファイルの全体を読み書きするのであれば、次に説明するPath
のread_text()
, write_text()
, read_bytes()
, write_bytes()
メソッドが便利。
テキストファイルの読み込み・書き込み: read_text(), write_text()
Path
のread_text()
メソッドでテキストファイルの中身全体を文字列として取得可能。
上のopen()
メソッドの説明で作成したファイルを読み込んで確認する。
p_new = Path('temp/new_file.txt')
s = p_new.read_text()
print(s)
# line 1
# line 2
# line 3
print(type(s))
# <class 'str'>
書き込みはwrite_text()
。
書き込んだ文字数が返される。追記ではなく上書きとなり元の内容は削除されるので注意。
i = p_new.write_text('new text')
print(i)
# 8
print(p_new.read_text())
# new text
存在しないファイルの場合、read_text()
はエラー。
p_new2 = Path('temp/new_file2.txt')
print(p_new2.exists())
# False
# print(p_new2.read_text())
# FileNotFoundError: [Errno 2] No such file or directory: 'temp/new_file2.txt'
write_text()
は新規作成となる。
print(p_new2.write_text('new text2'))
# 9
print(p_new2.read_text())
# new text2
touch()
の例と同じく、write_text()
で新規作成する場合も直上のディレクトリまでは作成しておかないとエラーとなる。
p_text_new_dir = Path('temp/new_dir2/new_file.txt')
# print(p_text_new_dir.write_text('new_text'))
# FileNotFoundError: [Errno 2] No such file or directory: 'temp/new_dir2/new_file.txt'
直上のディレクトリまで作成する方法はtouch()
のところで説明した通り。親ディレクトリのPath
オブジェクトをparent
属性で取得してmkdir()
でディレクトリを作成してからwrite_text()
を実行する。
p_text_new_dir.parent.mkdir(parents=True, exist_ok=True)
print(p_text_new_dir.write_text('new_text'))
# 8
print(p_text_new_dir.read_text())
# new_text
直上のディレクトリまで存在している場合は以下のように一行で書ける。
print(Path('temp/new_file3.txt').write_text('new_text3'))
# 9
print(Path('temp/new_file3.txt').read_text())
# new_text3
ファイルの中身を一行ずつ読み込んだり、追記したりする必要がなければopen()
よりもread_text()
, write_text()
のほうが簡単。
バイナリファイルの読み込み・書き込み: read_bytes(), write_bytes()
read_text()
, write_text()
のバイナリ版がread_bytes()
, write_bytes()
。
使い方はread_text()
, write_text()
と同じ。バイト列(bytes
)を読み書きできる。
p_bin = Path('temp/new_file.bin')
print(p_bin.write_bytes(b'binary'))
# 6
print(p_bin.read_bytes())
# b'binary'
ファイルを削除: unlink()
ファイルの削除はunlink()
。
p_empty = Path('temp/empty_file.txt')
print(p_empty.exists())
# True
p_empty.unlink()
print(p_empty.exists())
# False
デフォルトでは存在しないファイルに対してはエラー。
# p_empty.unlink()
# FileNotFoundError: [Errno 2] No such file or directory: 'temp/empty_file.txt'
Python 3.8でmissing_ok
引数が追加された。missing_ok=True
とすると存在しないファイルでもエラーにならない。
p_empty.unlink(missing_ok=True)
unlink()
で削除できるのはファイルとシンボリックリンク。ディレクトリを指すPath
オブジェクトではエラーとなる。
p_dir = Path('temp/')
# p_dir.unlink()
# PermissionError: [Errno 1] Operation not permitted: 'temp'
pathlibでのディレクトリの削除については以下の記事を参照。
一覧からすべてのファイルを削除
ディレクトリを示すPath
オブジェクトでiterdir()
メソッドを使うと、直下のファイル・ディレクトリのPath
オブジェクト一覧のイテレータが取得できる。
これを利用してディレクトリ直下のファイルをすべて削除できる。上述のようにunlink()
はディレクトリに対してはエラーとなるのでis_file()
で場合分けしている。
p_dir = Path('temp/')
for p in p_dir.iterdir():
if p.is_file():
p.unlink()
リスト内包表記を利用して一行で書くと以下のようになる。
- 関連記事: Pythonリスト内包表記の使い方
[p.unlink() for p in p_dir.iterdir() if p.is_file()]
iterdir()
ではなくglob()
を使うとファイル名やディレクトリ名をワイルドカード文字などの条件で抽出した一覧を取得可能。これに対して上述のようにunlink()
を適用すると条件を満たすファイルのみを削除できる。
pathlibでのファイル一覧の取得は以下の記事を参照。