[解決!Python]Path.existsメソッドを使ってパスが存在するかどうかを確認するには:解決!Python
pathlibモジュールのPathクラスが持つexistsメソッドを使って、パスが実際に存在するディレクトリやファイルを参照しているかを確認する方法を紹介する。
from pathlib import Path
mydir = Path('mydir')
myfile = Path('myfile.txt')
nofile_or_dir = Path('nofile_or_dir')
# mydirディレクトリとmyfile.txtファイルを作成
mydir.mkdir(exist_ok=True)
myfile.touch()
# existsメソッドはパスがディレクトリやファイルを指していればTrueを返す
print(mydir.exists()) # True
print(myfile.exists()) # True
print(nofile_or_dir.exists()) # False
# ディレクトリが存在しなければ作成する
if not mydir.exists(): # d.mkdir(exist_ok=True)
mydir.mkdir()
# ファイルが存在していればバックアップを取ってから書き込みを行う
if myfile.exists():
myfile.rename(myfile.stem + '.bak')
myfile.write_text('some text')
# 指定されたファイル/ディレクトリの存在確認の後、処理を振り分ける
def do_some_work(path):
if not path.exists():
res = input(f'{path} not exists. create it? (y/n)')
if res == 'y':
path.touch()
if path.is_dir():
print(f'{path} is a directory')
elif path.is_file():
print(f'{path} is a file')
else:
print(f'{path} is not a directory nor file')
paths = [mydir, myfile, nofile_or_dir]
for path in paths:
do_some_work(path)
Pathクラスのexistsインスタンスメソッド
pathlibモジュールのPathクラスにはexistsインスタンスメソッドが備わっている。existsメソッドは対象となるPathクラスのインスタンスがディレクトリかファイルを指していればTrueを、そうでなければFalseを返す(引数はない)。
以下に例を示す。
from pathlib import Path
mydir = Path('mydir')
myfile = Path('myfile.txt')
nofile_or_dir = Path('nofile_or_dir')
# mydirディレクトリとmyfile.txtファイルを作成
mydir.mkdir(exist_ok=True)
myfile.touch()
# existsメソッドはパスがディレクトリやファイルを指していればTrueを返す
print(mydir.exists()) # True
print(myfile.exists()) # True
print(nofile_or_dir.exists()) # False
この例では、最初にPathクラスをインポートした後で、mydirディレクトリとmyfile.txtファイルを作成している(ディレクトリの作成については「ディレクトリを作成/削除するには:pathlibモジュール編」を、ファイルの作成については「ファイルを作成/削除するには」を参照のこと)。
最後の3行では存在しないパス「nofile_or_dir」への参照を含む、3つのPathクラスのインスタンスについてexistsメソッドを呼び出している。mydirディレクトリとmyfile.txtファイルは存在しているのでTrueが、nofile_or_dirについてはそのようなディレクトリもファイルも存在していないのでFalseが返される。
このメソッドは例えば、ユーザーが指定したり、設定ファイルから読み出したりしたパスが実際に存在するかどうかを確認してから、何らかの処理を行う場合に使える。
例えば、指定されたディレクトリがなければ作成し、既に存在していれば何もしないという場合には以下のようなコードが書けるだろう(上でも見たが、これは冗長であり、Path.mkdirインスタンスメソッドならexist_ok引数にTrueを指定した方がスマートである)。
if not mydir.exists(): # d.mkdir(exist_ok=True)
mydir.mkdir()
また、ファイルを新規に作成して、そこに何かを書き込みたいが、同名のファイルがあればそのファイルの拡張子を「.bak」に変更する必要があるといった場合には次のようなコードが書ける。
if myfile.exists():
myfile.rename(myfile.stem + '.bak')
myfile.write_text('some text')
この例ではexistsメソッドでパスが存在しているかどうかを確認し、myfileが指すファイルの名前をrenameメソッドで「元ファイルのベース部分.bak」に変更してから(この場合は「myfile.bak」になる)、myfile.txtファイルに「some text」を書き込んでいる(renameメソッドによりmyfileが指すファイルの名前は変わり、書き込みを行うまでは、myfile自体は存在しないファイル「myfile.txt」を指していることに注意)。
このように「パスの存在確認」に続けて何かの処理を行うことはよくあるだろう。そのときには「パスがディレクトリやファイルであるかどうかを調べるには:pathlibモジュール編」で紹介したis_dir/is_fileメソッドと組み合わせることが考えられる。
以下に例を示す。do_some_work関数はPathクラスのインスタンスを受け取り、そのパスが存在するかどうかを確認した後に、is_dirメソッドとis_fileメソッドを使って処理を切り分けている。
def do_some_work(path):
if path.exists():
if path.is_dir():
print(f'{path} is a directory')
elif path.is_file():
print(f'{path} is a file')
else:
print(f'{path} is not a directory nor file')
else:
print(f'{path} not exists')
paths = [mydir, myfile, nofile_or_dir]
for path in paths:
do_some_work(path)
このようなネストしたif文を書いてしまいそうになるが(実際、筆者もこれでよいだろうとサンプルコードを書いていた)、is_dir/is_fileメソッドは対象が存在しなければFalseを返すので上のようにネストさせる必要はない。以下のコードで十分な場合もあるだろう。
def do_some_work(path):
if path.is_dir():
print(f'{path} is a directory')
elif path.is_file():
print(f'{path} is a file')
else:
print(f'{path} is not a directory nor file')
paths = [mydir, myfile, nofile_or_dir]
for path in paths:
do_some_work(path)
existsメソッドを使った条件分岐はis_dir/is_fileメソッドによる分岐からは独立させて「パスが存在しない場合」にディレクトリやファイルを作成してから、その後の処理を続けるような使い方をするのがよいかもしれない。
def do_some_work(path):
if not path.exists(): # パスが存在しなければファイルを作成するかを尋ねる
res = input(f'{path} not exists. create it? (y/n)')
if res == 'y':
path.touch()
if path.is_dir():
print(f'{path} is a directory')
elif path.is_file():
print(f'{path} is a file')
else:
print(f'{path} is not a directory nor file')
paths = [mydir, myfile, nofile_or_dir]
for path in paths:
do_some_work(path)
Copyright© Digital Advantage Corp. All Rights Reserved.