Как проверить, существует ли файл

Обновлено: 21.11.2024

Некоторая информация относится к предварительной версии продукта, которая может быть существенно изменена до ее выпуска. Microsoft не дает никаких явных или подразумеваемых гарантий в отношении представленной здесь информации.

Определяет, существует ли указанный файл.

Параметры

Файл для проверки.

Возврат

true, если вызывающий объект имеет необходимые разрешения и путь содержит имя существующего файла; в противном случае ложь. Этот метод также возвращает false, если path имеет значение null , недопустимый путь или строку нулевой длины. Если вызывающий объект не имеет достаточных прав для чтения указанного файла, исключение не создается, и метод возвращает значение false независимо от наличия пути .

Примеры

В следующем примере определяется, существует ли файл.

Примечания

Метод Exists не следует использовать для проверки пути, этот метод просто проверяет, существует ли файл, указанный в пути. Передача недопустимого пути в Exists возвращает false . Чтобы проверить, содержит ли путь какие-либо недопустимые символы, вы можете вызвать метод GetInvalidPathChars для извлечения символов, недопустимых для файловой системы. Вы также можете создать регулярное выражение, чтобы проверить, является ли путь допустимым для вашей среды. Примеры допустимых путей см. в разделе Файл.

Чтобы проверить, существует ли каталог, см. Directory.Exists.

Имейте в виду, что другой процесс потенциально может что-то сделать с файлом в промежутке между вызовом метода Exists и выполнением над файлом другой операции, например удаления.

В параметре пути разрешено указывать информацию об относительном или абсолютном пути. Информация об относительном пути интерпретируется как относительная к текущему рабочему каталогу. Чтобы получить текущий рабочий каталог, см. GetCurrentDirectory.

Если path описывает каталог, этот метод возвращает false . Конечные пробелы удаляются из параметра пути перед определением существования файла.

Метод Exists возвращает значение false, если возникает какая-либо ошибка при попытке определить, существует ли указанный файл. Это может произойти в ситуациях, вызывающих исключения, например, при передаче имени файла с недопустимыми символами или слишком большим количеством символов, неисправном или отсутствующем диске или если вызывающая сторона не имеет разрешения на чтение файла.

Вывод: в этом руководстве вы узнаете, как проверить, существует ли файл.

При обработке файлов часто требуется проверить, существует ли файл, прежде чем выполнять с ним какие-либо действия, например чтение из файла или запись в него.

Для этого вы можете использовать функцию exists() из модуля os.path или метод is_file() из класса Path в модуле pathlib.

функция os.path.exists()

Метод Path.is_file()

1) Использование функции os.path.exists() для проверки существования файла

Чтобы проверить, существует ли файл, вы передаете путь к файлу функции exists() из стандартной библиотеки os.path.

Сначала импортируйте стандартную библиотеку os.path:

Во-вторых, вызовите функцию exists():

Если файл существует, функция exists() возвращает значение True . В противном случае возвращается False .

Если файл находится в той же папке, что и программа, path_to_file — это просто имя файла.

Однако это не так, вам нужно передать полный путь к файлу. Например:

Даже если вы запускаете программу в Windows, вы должны использовать косую черту ( / ) для разделения пути. Он будет работать в Windows, macOS и Linux.

В следующем примере используется функция exists() для проверки существования файла readme.txt в той же папке, что и программа:

Если файл readme.txt существует, вы увидите следующий вывод:

В противном случае на экране появится False:

Чтобы сделать вызов функции exists() короче и более очевидным, вы можете импортировать эту функцию и переименовать ее в функцию file_exists() следующим образом:

2) Использование модуля pathlib для проверки существования файла

Python представил модуль pathlib начиная с версии 3.4.

Модуль pathlib позволяет вам манипулировать файлами и папками, используя объектно-ориентированный подход. Если вы не знакомы с объектно-ориентированным программированием, ознакомьтесь с разделом Python OOP.

Сначала импортируйте класс Path из модуля pathlib:

Затем создайте новый экземпляр класса Path и инициализируйте его путем к файлу, существование которого вы хотите проверить:

Наконец, проверьте, существует ли файл, используя метод is_file():

Если файл не существует, метод is_file() возвращает значение False. В противном случае возвращается True .

Как проверить, существует ли файл, не используя оператор try?

Чтобы проверить, существует ли объект Path независимо от того, является ли он файлом или каталогом, используйте my_path.exists() .

my_path.exists() недостаточно. my_path.is_file() сообщит вам, является ли это файлом (может быть полезно для чтения).Но если вы хотите создать файл, вы также должны проверить его существование, чтобы исключить каталоги или другие нефайловые объекты в файловой системе, которые могут привести к сбою.

39 ответов 39

Если причина, по которой вы проверяете, заключается в том, что вы можете сделать что-то вроде if file_exists: open_it() , безопаснее использовать попытку вместо попытки открыть его. Проверка и последующее открытие могут привести к удалению или перемещению файла или к чему-то еще между моментом проверки и попыткой открыть его.

Если вы не планируете открывать файл немедленно, вы можете использовать os.path.isfile

Возвращает True, если путь является существующим обычным файлом. Это следует за символическими ссылками, поэтому и islink(), и isfile() могут быть истинными для одного и того же пути.

если вам нужно убедиться, что это файл.

Начиная с Python 3.4, модуль pathlib предлагает объектно-ориентированный подход (перенесенный обратно в pathlib2 в Python 2.7):

Чтобы проверить каталог, выполните следующие действия:

Чтобы проверить, существует ли объект Path независимо от того, является ли он файлом или каталогом, используйте exists() :

Вы также можете использовать resolve(strict=True) в блоке try:

относительно первого примечания (используйте «попробовать», если проверяете перед открытием), к сожалению, это не сработает, если вы хотите открыть для добавления, будучи уверенным, что оно существует раньше, поскольку режим «а» создаст, если не существует.

Подождите, значит pathlib2 pathlib ? pathlib для python3, верно? Я использовал pathlib2, думая, что он лучше.

@kyrill: Открытие файла для добавления — это не то же самое, что открытие его для записи и поиск до конца: когда у вас есть параллельные записи, они будут перезаписывать друг друга без 'a' .

У вас есть функция os.path.exists:

Это возвращает True как для файлов, так и для каталогов, но вместо этого вы можете использовать

чтобы проверить, является ли это конкретным файлом. Он следует за символическими ссылками.

В отличие от isfile(), exists() возвращает True для каталогов. Таким образом, в зависимости от того, нужны ли вам только простые файлы или каталоги, вы будете использовать isfile() или exists() . Вот простой вывод REPL:

Поскольку вы импортируете os , вам не нужно снова импортировать os.path, так как он уже является частью os . Вам просто нужно импортировать os.path, если вы собираетесь использовать только функции из os.path, а не из самой ОС, чтобы импортировать меньшую вещь, но поскольку вы используете os.access и os.R_OK, второй импорт не нужен. .

Проверка наличия у пользователя прав доступа для чтения файла выполняется очень профессионально. Часто данные находятся на локальном диске во время разработки и в сетевой папке в процессе производства. Тогда это может привести к такой ситуации. Кроме того, код совершенно ясен, удобочитаем и ясен.

Хотя почти все возможные способы были перечислены (по крайней мере, в одном из) существующих ответов (например, был добавлен Python 3.4), я попытаюсь сгруппировать все вместе.

Примечание: каждый фрагмент кода стандартной библиотеки Python, который я собираюсь опубликовать, относится к версии 3.5.3.

Постановка задачи:

Возможные решения:

[Python 3]: os.path.exists(path) (также проверьте другие члены семейства функций, такие как os.path.isfile , os.path.isdir , os.path.lexists на наличие разное поведение)

Возвращает True, если путь указывает на существующий путь или дескриптор открытого файла. Возвращает False для неработающих символических ссылок. На некоторых платформах эта функция может возвращать значение False, если не предоставлено разрешение на выполнение os.stat() для запрошенного файла, даже если путь физически существует.

Все хорошо, но если следовать дереву импорта:

os.path — posixpath.py (ntpath.py)

это просто блок try / except вокруг [Python 3]: os.stat(path, *, dir_fd=None, follow_symlinks=True). Итак, ваш код try / кроме свободен, но ниже в стеке кадров есть (по крайней мере) один такой блок. Это также относится к другим функциям (включая os.path.isfile ).

    Это более изящный (и более pythonic) способ обработки путей, но

И его использование — я воспроизведу поведение файла os.path.isfile (обратите внимание, что это только для демонстрации, не пытайтесь написать такой код для производства):

Используйте [Python 3]: contextlib.suppress(*exceptions), который был специально разработан для выборочного подавления исключений

Но они, похоже, являются обертками над блоками try / except / else / finally, поскольку [ Python 3]: оператор with гласит:

Это позволяет обычную попытку. Кроме. наконец, шаблоны использования должны быть инкапсулированы для удобного повторного использования.

Функции обхода файловой системы (и поиск результатов для соответствующих элементов))

Под капотом оба используют:

Использование scandir() вместо listdir() может значительно повысить производительность кода, которому также требуется информация о типе файла или атрибуте файла, поскольку объекты os.DirEntry предоставляют эту информацию, если операционная система предоставляет ее при сканировании каталога. . Все ос.Методы DirEntry могут выполнять системный вызов, но is_dir() и is_file() обычно требуют системного вызова только для символических ссылок; os.DirEntry.stat() всегда требует системного вызова в Unix, но требует его только для символических ссылок в Windows.

  • Используется os.listdir ( os.scandir, если доступно)
  • Не похоже на функцию обхода сама по себе (по крайней мере, в некоторых случаях), но она по-прежнему использует os.listdir

Поскольку они перебирают папки (в большинстве случаев) они неэффективны для нашей проблемы (есть исключения, такие как globbing без подстановочных знаков — как указал @ShadowRanger), поэтому я Я не собираюсь настаивать на них. Не говоря уже о том, что в некоторых случаях может потребоваться обработка имени файла.

    разрешения пользователя могут ограничивать «видимость» файла, как указано в документе:

<блочная цитата>

. проверить, есть ли у вызывающего пользователя указанный доступ к path. режим должен быть F_OK, чтобы проверить существование пути.

Поскольку я также работаю в C, я также использую этот метод, потому что внутри он вызывает собственные API (опять же, через "$/ Modules/posixmodule.c"), но он также открывает ворота для возможных ошибок пользователя и не так Pythonic, как другие варианты. Итак, как правильно заметил @AaronHall, не используйте его, если не знаете, что делаете:

  • Nix: [man7]: ACCESS(2) (. обратите внимание на примечание о дыре в безопасности, которую может создать его использование. )
  • Win: [MS.Docs]: функция GetFileAttributesW

Примечание. Вызов нативных API также возможен через [Python 3]: ctypes — внешнюю библиотеку функций для Python, но в большинстве случаев это сложнее.< /p>

(только для Win): поскольку vcruntime* (msvcr*) .dll экспортирует файл [MS. Docs]: _access, а также семейство функций _waccess, вот пример:

Примечания:

  • Хотя это и не рекомендуется, я использую в вызове os.F_OK, но это просто для ясности (его значение равно 0)
  • Я использую _waccess, чтобы один и тот же код работал на Python3 и Python2 (несмотря на юникод). > связанные различия между ними)
  • Хотя это касается очень конкретной области, об этом не упоминалось ни в одном из предыдущих ответов.

Аналог Lnx (Ubtu (16 x 64)):

Примечания:

Вместо жестко заданного пути libc ("/lib/x86_64-linux-gnu/libc.so.6"), который может (и, скорее всего, будет) зависит от системы, None (или пустая строка) может быть передана в конструктор CDLL ( ctypes.CDLL(None).access(b"/tmp", os.F_OK ) ). Согласно [man7]: DLOPEN(3):

Если имя_файла равно NULL, возвращаемый дескриптор относится к основной программе. При задании dlsym() этот дескриптор вызывает поиск символа в основной программе, за которым следуют все общие объекты, загружаемые при запуске программы, а затем все общие объекты, загружаемые dlopen() с флагом RTLD_GLOBAL.

< /цитата>
  • Основная (текущая) программа (python) связана с libc, поэтому ее символы (включая доступ) будут загружены
  • С этим нужно обращаться осторожно, поскольку доступны такие функции, как main, Py_Main и (все) другие; вызов их может иметь катастрофические последствия (для текущей программы)
  • Это также не относится к Win (но это не так уж важно, так как msvcrt.dll находится в "%SystemRoot%\System32 ", который по умолчанию находится в %PATH%). Я хотел пойти дальше и воспроизвести это поведение на Win (и отправить исправление), но, как оказалось, [MS.Docs]: функция GetProcAddress "видит" только экспортированные символы, поэтому, если кто-то объявляет функции в основном исполняемом файле как __declspec(dllexport) (с какой стати обычный человек должен это делать?), основная программа загружается, но в значительной степени непригодна для использования

Установите сторонний модуль с возможностями файловой системы

Скорее всего, будет полагаться на один из вышеперечисленных способов (возможно, с небольшими настройками).
Одним из примеров может быть (опять же, для Win) [GitHub]: mhammond/pywin32 — Расширения Python для Windows (pywin32), которые являются оболочкой Python поверх WINAPI.

Но поскольку это скорее обходной путь, я останавливаюсь на этом.

Еще один (неубедительный) обходной путь (gainarie) — это (как я люблю его называть) подход системного администратора: используйте Python в качестве оболочка для выполнения команд оболочки

Итог:

  • Используйте блоки try / except / else / finally, потому что они могут помешать вам столкнуться с череда неприятных проблем.Контрпример, который я могу придумать, это производительность: такие блоки стоят дорого, поэтому старайтесь не размещать их в коде, который должен выполняться сотни тысяч раз в секунду (но поскольку (в большинстве случаев) он требует доступа к диску, такого не будет).

Последнее примечание(я):

  • Я постараюсь поддерживать его в актуальном состоянии, любые предложения приветствуются, я включу все полезное, что придет в ответ

Можете ли вы уточнить это утверждение? "Хотя это не очень хорошая практика, я использую os.F_OK в вызове, но это просто для ясности (его значение равно 0)"

@sk8asd123: Довольно сложно сделать это в комментарии: обычно лучше использовать константы с функциями, с которыми они связаны. Это применимо при работе с несколькими модулями, определяющими одну и ту же константу, потому что некоторые из них могут быть устаревшими, и лучше всего, чтобы функции и константы были синхронизированы. При работе с ctypes (вызов функций напрямую) я должен был определить константу (из MSDN) или вообще не использовать константу. Это просто рекомендация, которую я использую, в 99,9% случаев это, вероятно, не имеет значения (функционально).

@CristiFati: Начиная с версии 3.6, glob.iglob (а также glob.glob) основаны на os.scandir , так что теперь это лениво; чтобы получить первое попадание в каталог из 10 М файлов, вы сканируете только до тех пор, пока не достигнете первого попадания. И даже до версии 3.6, если вы используете методы glob без каких-либо подстановочных знаков, функция умна: она знает, что у вас может быть только одно совпадение, поэтому она упрощает подстановку только до os.path.isdir или os.path.lexists ( в зависимости от того, заканчивается ли путь на / ).

Эта вторая часть моего комментария (подстановка без подстановочных знаков на самом деле не выполняет итерацию папки и никогда не выполняла) означает, что это совершенно эффективное решение проблемы (медленнее, чем прямой вызов os.path.isdir или os.path .lexist, так как это набор вызовов функций на уровне Python и строковых операций, прежде чем он решит, что эффективный путь является жизнеспособным, но без дополнительных системных вызовов или операций ввода-вывода, что на несколько порядков медленнее).

Python 3.4+ имеет модуль объектно-ориентированного пути: pathlib. Используя этот новый модуль, вы можете проверить, существует ли файл следующим образом:

Вы можете (и обычно должны) использовать блок try/except при открытии файлов:

В модуле pathlib есть много интересных вещей: удобная подстановка, проверка владельца файла, более простое объединение путей и т. д. Это стоит проверить. Если вы используете более раннюю версию Python (версия 2.6 или более поздняя), вы все равно можете установить pathlib с помощью pip:

Затем импортируйте его следующим образом:

Это самый простой способ проверить, существует ли файл. Тот факт, что файл существовал, когда вы проверили, не гарантирует, что он будет там, когда вам нужно будет его открыть.

Пока вы намереваетесь получить доступ к файлу, условие гонки существует, независимо от того, как построена ваша программа. Ваша программа не может гарантировать, что другой процесс на компьютере не изменил файл. Это то, что Эрик Липперт называет экзогенным исключением. Вы не можете избежать этого, предварительно проверив существование файла.

@IsaacSupeene Лучше всего сделать окно операции (файла) как можно меньше, а затем обеспечить правильную обработку исключений

Как проверить, существует ли файл, используя Python, без использования оператора try?

Теперь доступно, начиная с Python 3.4, импортируйте и создайте экземпляр объекта Path с именем файла и проверьте метод is_file (обратите внимание, что он также возвращает True для символических ссылок, указывающих на обычные файлы):

Если вы используете Python 2, вы можете сделать резервную копию модуля pathlib из pypi, pathlib2 или иным образом проверить isfile из модуля os.path:

Теперь приведенное выше, вероятно, лучший прагматичный прямой ответ здесь, но есть вероятность состояния гонки (в зависимости от того, чего вы пытаетесь достичь), и тот факт, что базовая реализация использует try , но Python использует try везде в его реализации.

Поскольку Python использует try везде, нет причин избегать реализации, в которой он используется.

Но остальная часть этого ответа пытается учесть эти предостережения.

Длинный и более педантичный ответ

Доступно, начиная с Python 3.4, используйте новый объект Path в pathlib . Обратите внимание, что .exists — это не совсем правильно, потому что каталоги — это не файлы (за исключением того, что в понимании Unix все является файлом).

Поэтому нам нужно использовать is_file :

Вот справка по is_file :

Итак, давайте получим файл, который, как мы знаем, является файлом:

По умолчанию NamedTemporaryFile удаляет файл при закрытии (и автоматически закрывается, когда на него больше нет ссылок).

Если вы покопаетесь в реализации, то увидите, что is_file использует try :

Условия гонки: почему нам нравится пробовать

Нам нравится try, потому что он позволяет избежать условий гонки. С помощью try вы просто пытаетесь прочитать свой файл, ожидая, что он там есть, а если нет, вы перехватываете исключение и выполняете любое резервное поведение, которое имеет смысл.

Если вы хотите убедиться, что файл существует, прежде чем пытаться его прочитать, и вы можете удалить его, а затем использовать несколько потоков или процессов, или другая программа знает об этом файле и может удалить его, вы рискуете вероятность состояния гонки, если вы проверите, что оно существует, потому что тогда вы гонитесь, чтобы открыть его до того, как его состояние (его существование) изменится.

Состояния гонки очень сложно отлаживать, потому что существует очень маленькое окно, в котором они могут привести к сбою вашей программы.

Но если это ваша мотивация, вы можете получить значение оператора try с помощью диспетчера контекста подавления.

Как избежать условий гонки без оператора try: подавить

Python 3.4 предоставляет нам менеджер контекста подавления (ранее диспетчер контекста игнорирования), который семантически делает то же самое, но в меньшем количестве строк, а также (по крайней мере, поверхностно) выполняет исходный запрос, чтобы избежать оператора try:

Для более ранних версий Python вы могли использовать свой собственный submit , но без try это будет более многословно, чем с помощью. Я действительно считаю, что на самом деле это единственный ответ, который не использует try на любом уровне в Python, который можно применить до Python 3.4, потому что вместо этого он использует диспетчер контекста:

Возможно, проще попробовать:

Другие варианты, которые не соответствуют требованию "без попытки":

isfile

os.path.isfile(path)

Возвращает True, если путь является существующим обычным файлом. Это следует за символическими ссылками, поэтому и islink(), и isfile() могут быть истинными для одного и того же пути.

Но если вы изучите исходный код этой функции, вы увидите, что в ней действительно используется оператор try:

Все, что он делает, это использует заданный путь, чтобы увидеть, может ли он получить статистику по нему, перехватывая OSError, а затем проверяя, является ли это файлом, если он не вызвал исключение.

Если вы собираетесь что-то сделать с файлом, я бы посоветовал напрямую попытаться сделать это с помощью try-except, чтобы избежать состояния гонки:

os.access

Для Unix и Windows доступен os.access , но для его использования необходимо передать флаги, и он не различает файлы и каталоги. Это больше используется для проверки того, имеет ли реальный вызывающий пользователь доступ в среде с повышенными привилегиями:

Он также страдает от тех же проблем с состоянием гонки, что и isfile . Из документов:

Примечание. Использование access() для проверки авторизации пользователя, например. открыть файл перед тем, как это сделать, с помощью open() создает брешь в безопасности, потому что пользователь может использовать короткий интервал времени между проверкой и открытием файла, чтобы манипулировать им. Предпочтительнее использовать методы EAFP. Например:

лучше написать так:

Избегайте использования os.access . Это функция низкого уровня, которая имеет больше возможностей для ошибок пользователя, чем объекты и функции более высокого уровня, рассмотренные выше.

Критика другого ответа:

В другом ответе говорится об os.access :

Лично я предпочитаю этот, потому что внутри он вызывает нативные API (через "$/Modules/posixmodule.c"), но также открывает ворота для возможных пользовательских ошибок, и это не так, как Pythonic как и другие варианты:

В этом ответе говорится, что он предпочитает не-Pythonic, подверженный ошибкам метод без каких-либо обоснований. Похоже, это побуждает пользователей использовать низкоуровневые API, не разбираясь в них.

Он также создает менеджер контекста, который, безоговорочно возвращая True , позволяет всем исключениям (включая KeyboardInterrupt и SystemExit !) проходить без уведомления, что является хорошим способом скрыть ошибки.

Проверка существования определенного файла или каталога в Python используется по-разному. Модуль os включает три метода, которые можно использовать для проверки существования определенного файла или каталога: isfile(), isdir() и exists()<. /эм>.

В этом руководстве мы обсудим, как можно проверить, существует ли определенный файл или каталог, используя функции isfile(), isdir() и exists. () в Python. Мы рассмотрим несколько примеров каждого из этих методов в действии, чтобы проиллюстрировать, как они работают.

Обновление ОС

Встроенный в Python модуль os позволяет вам получать доступ к функциям операционной системы в вашем коде.

Os — это модуль Python, а это значит, что перед его использованием нам нужно импортировать модуль в наш код. Мы будем использовать функции модуля path point только для проверки существования определенных файлов или каталогов. Итак, нам нужно только импортировать модуль os.path.

Python Проверить, существует ли файл

Метод os.path.isfile() проверяет, существует ли файл в Python. os.path.isfile() возвращает True или False, в зависимости от того, можно ли найти этот файл. Этот метод возвращает False, если вы указываете каталог в качестве аргумента.

Вот синтаксис метода isfile():

81 % участников заявили, что стали более уверенными в своих перспективах работы в сфере технологий после посещения учебного курса.Примите участие в тренировочном лагере сегодня.

Найдите подходящий вариант для буткемпа

В среднем выпускник буткемпа тратит менее шести месяцев на смену карьеры, начиная с буткемпа и заканчивая поиском своей первой работы.

Начните сменить профессию сегодня

isfile() принимает один аргумент: имя файла, существование которого вы хотите проверить. «путь» представляет собой путь к файлу в приведенном выше примере. Давайте рассмотрим пример, чтобы показать, как вы можете проверить, существует ли файл в Python.

Проверить, существует ли файл, пример Python

Скажем, мы создаем программу, которая анализирует данные об урожае авокадо для местной фермы. Прежде чем проводить наш анализ, мы хотим проверить, есть ли у нас обработанный файл, в котором мы можем хранить наши проанализированные данные. Если файл не существует, нам нужно будет его создать.

Наш обработанный файл должен называться ./final_data.csv. Мы можем использовать следующий код, чтобы проверить, существует ли этот файл:

Если наш путь к файлу существует, наш код вернет логическое значение Python True. Если существующего файла нет (и, следовательно, нет существующего пути к файлу), наш код вернет False.

Метод isfile() работает только для файлов; это не работает для каталогов. Если вы используете isfile() для проверки существования каталога, метод вернет False. Вот пример использования isfile() для проверки существования каталога:

Читайте также: