В программировании есть несколько способов решить задачу, и особенно это верно в Python. Вы не один раз обнаружите, что множество встроенных или стандартных модулей делают одно и то же, но с немного разной функциональностью. Проверка наличия файла или директории с использованием Python как раз из их числа.
Вот несколько способов проверить существование файлов/каталогов и их особенности. В этих примерах мы предположим, что наша текущая рабочая директория содержит эти файлы и каталоги:
drwxr-xr-x 3 scott staff 102 Jan 12 10:01 dir -rw-r--r-- 1 scott staff 5 Jan 12 09:56 file.txt lrwxr-xr-x 1 scott staff 8 Jan 12 09:56 link.txt -> file.txt lrwxr-xr-x 1 scott staff 3 Jan 12 10:00 sym -> dir
Заметьте, что у нас есть одна директория (dir
), один файл (file.txt
), одна символическая ссылка (симлинк) (link.txt
) и одна ссылка на каталог (sym
).
Оглавление
Проверка наличия файла
Это предположительно самый простой способ удостовериться, что файл существует и что это файл.
import os os.path.isfile('./file.txt') # True os.path.isfile('./link.txt') # True os.path.isfile('./fake.txt') # False os.path.isfile('./dir') # False os.path.isfile('./sym') # False os.path.isfile('./foo') # False
Обратите внимание, что os.path.isfile
следит за симлинками, так что мы получаем True
при проверке link.txt
.
isfile
, по сути, просто вспомогательный метод, который внутри использует os.stat
и stat.S_ISREG(mode)
, которые мы рассмотрим позже.
Проверка наличия каталога
Как и метод isfile
, os.path.isdir
— самый лёгкий способ убедиться, что директория существует и соответствует указанному пути.
import os os.path.isdir('./file.txt') # False os.path.isdir('./link.txt') # False os.path.isdir('./fake.txt') # False os.path.isdir('./dir') # True os.path.isdir('./sym') # True os.path.isdir('./foo') # False
Вновь, как и isfile
, os.path.isdir
следит за симлинками. Это всего лишь простая оболочка вокруг os.stat
и stat.S_ISDIR(mode)
, так что вы мало что получаете от этого, кроме удобства.
Проверка наличия файла или каталога
Другой способ проверить, есть ли путь (когда вам не так важно, на файл он указывает или на директорию) — применить os.path.exists
.
import os os.path.exists('./file.txt') # True os.path.exists('./link.txt') # True os.path.exists('./fake.txt') # False os.path.exists('./dir') # True os.path.exists('./sym') # True os.path.exists('./foo') # False
Как видно, не имеет значения, на что указывает путь: на файл, на директорию, на симлинк, что похоже на isfile(path) или isdir(path)
. Но на самом деле, внутри метод пытается вызвать os.stat(path)
, и при получении ошибки он возвращает False
.
Дополнительно
На протяжении статьи я упоминал, как все эти методы используют os.stat
, поэтому я решил, что будет полезно взглянуть на него. Это низкоуровневый метод, который предоставит вам сведения о файлах, каталогах, сокетах, буферах и так далее.
Как и все остальные рассмотренные нами методы, os.stat
следит за симлинками, так что если вы хотите получить информацию о ссылке, попробуйте вместо него метод os.lstat()
.
Поскольку все операционные системы различны, данные, полученные от метода os.stat
, сильно отличаются. Вот некоторые данные, которыми располагает каждая операционная система:
st_mode
: защитные битыst_uid
: пользовательский id владельцаst_gid
: групповой id владельцаst_size
: размер файла в байтахst_atime
: время ближайшего доступаst_mtime
: время ближайшего измененияst_ctime
: время ближайшего изменения метаданных в Unix, или время создания в Windows
Затем вы можете использовать эти данные с помощью модуля stat
, чтобы получить интересующую информацию, например, указывает ли путь на сокет (stat.S_ISSOCK(mode)
), или же это именованный канал (stat.S_ISFIFO(mode)
).
Если вам нужна более продвинутая функциональность, вам следует идти именно сюда. Но в 90% случаев, когда вы обращаетесь с директориями и файлами, модули os
или os.path
содержат всё, что вам нужно.
Хотя есть один реальный пример, когда вы много раз тестируете один и тот же файл и хотите избежать слишком больших расходов при использовании системного вызова stat для каждого теста. Так что если нам надо сделать несколько тестов, это поможет вам решить задачу более эффективно.