Python, pathlibでファイルの作成・open・読み書き・削除
Pythonのpathlibモジュールを使ってファイルを新規作成したり読み込み・書き込みを行ったり削除したりする方法について説明する。
pathlibで扱うPath
オブジェクトにはopen()
メソッドがあり、組み込み関数open()
と同様の処理が可能。また、テキストファイルやバイナリファイルを読み書きするためのread_text()
, write_text()
, read_bytes()
, write_bytes()
という非常に便利なメソッドもある。
pathlibはPython3.4から追加されたモジュール。ファイルやディレクトリ(フォルダ)のパスをオブジェクトとして操作できる。標準ライブラリに含まれているので追加のインストールは不要(import
は必要)。
ここでは以下の内容について説明する。
- 空のファイルを作成、既存ファイルの日時更新:
touch()
- ファイルのopen:
open()
- テキストファイルの読み込み・書き込み:
read_text()
,write_text()
- バイナリファイルの読み込み・書き込み:
read_bytes()
,write_bytes()
- ファイルを削除:
unlink()
- 一覧からすべてのファイルを削除
組み込み関数open()
についての詳細は以下の記事を参照。
pathlibの基礎、ディレクトリの処理については以下の記事を参照。
空のファイルを作成、既存ファイルの日時更新: touch()
空のファイルを作成するにはPath
オブジェクトのtouch()
メソッドを使う。
pathlib.Path()
でPath
オブジェクトを生成する。ここではディレクトリを作成し、その中の新たなファイルのパスを指定する。
import pathlib
import os
os.makedirs('temp', exist_ok=True)
p_empty = pathlib.Path('temp/empty_file.txt')
print(p_empty)
# temp/empty_file.txt
print(type(p_empty))
# <class 'pathlib.PosixPath'>
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'
新規ファイルを作成する場合は直上のディレクトリまでは作成しておく必要がある。中間ディレクトリが存在しないとエラー。
# pathlib.Path('temp/new_dir/empty_file.txt').touch()
# FileNotFoundError: [Errno 2] No such file or directory: 'temp/new_dir/empty_file.txt'
中間ディレクトリが存在していない場合は、親ディレクトリのPath
オブジェクトをparent
属性で取得してmkdir()
でディレクトリを作成してからtouch()
を実行する。
p_empty_new = pathlib.Path('temp/new_dir/empty_file.txt')
p_empty_new.parent.mkdir(parents=True, exist_ok=True)
p_empty_new.touch()
直上のディレクトリまで存在している場合は以下のように一行で書ける。
pathlib.Path('temp/empty_file2.txt').touch()
ファイルのopen: open()
Path
オブジェクトのopen()
メソッドで、Path
オブジェクトが指すファイルに対して組み込み関数open()
と同じ処理が可能。
引数mode
を'w'
とすると書き込みモード。存在しないファイルを指すパスでは新規作成となる。
p_new = pathlib.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()
メソッドで作成したファイルの中身を読み込んで確認する。
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 = pathlib.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()
で新規作成する場合も直上のディレクトリまでは作成しておかないとエラーとなる。
# print(pathlib.Path('temp/new_dir2/new_file.txt').write_text('new_text'))
# FileNotFoundError: [Errno 2] No such file or directory: 'temp/new_dir2/new_file.txt'
直上のディレクトリまで作成する方法はtouch()
のところで説明した通り。
p_text_new = pathlib.Path('temp/new_dir2/new_file.txt')
p_text_new.parent.mkdir(parents=True, exist_ok=True)
print(p_text_new.write_text('new_text'))
# 8
print(p_text_new.read_text())
# new_text
直上のディレクトリまで存在している場合は以下のように一行で書ける。
print(pathlib.Path('temp/new_file3.txt').write_text('new_text3'))
# 9
print(pathlib.Path('temp/new_file3.txt').read_text())
# new_text3
一行ずつ読み込んだり、追記したりする必要がなければopen()
よりもread_text()
, write_text()
のほうがはるかに楽。
pathlibモジュールはPython3.4から追加されたが、read_text()
, write_text()
はPython3.5から追加されたメソッド。バージョンに注意。
バイナリファイルの読み込み・書き込み: read_bytes(), write_bytes()
read_text()
, write_text()
のバイナリ版がread_bytes()
, write_bytes()
。
- pathlib - read_bytes() --- オブジェクト指向のファイルシステムパス — Python 3.7.1rc1 ドキュメント
- pathlib - write_bytes() --- オブジェクト指向のファイルシステムパス — Python 3.7.1rc1 ドキュメント
使い方はread_text()
, write_text()
と同じ。
read_bytes()
, write_bytes()
もPython3.5から追加された。
ファイルを削除: unlink()
ファイルの削除はunlink()
。
p_empty = pathlib.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'
unlink()
で削除できるのはファイルとシンボリックリンク。ディレクトリを指すPath
オブジェクトではエラーとなる。
p_dir = pathlib.Path('temp/')
# p_dir.unlink()
# PermissionError: [Errno 1] Operation not permitted: 'temp'
pathlibでのディレクトリの削除は以下の記事を参照。
一覧からすべてのファイルを削除
ディレクトリを示すPath
オブジェクトでiterdir()
メソッドを使うと、直下のファイル・ディレクトリのPath
オブジェクト一覧のイテレータが取得できる。
これを利用してディレクトリ直下のファイルをすべて削除できる。上述のようにunlink()
はディレクトリに対してはエラーとなるのでis_file()
で場合分けしている。
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でのファイル一覧の取得は以下の記事を参照。