Как проверить, существует файл или нет, без использования try
оператора?
источник
Как проверить, существует файл или нет, без использования try
оператора?
Если причина, по которой вы проверяете, заключается в том, что вы можете сделать что-то подобное if file_exists: open_it()
, безопаснее использовать try
вокруг попытки открыть его. Проверка и последующее открытие может привести к удалению или перемещению файла, а также к тому, что вы проверяете и когда пытаетесь открыть его.
Если вы не планируете открыть файл сразу, вы можете использовать os.path.isfile
Вернуть,
True
если путь является существующим обычным файлом. Это следует за символическими ссылками, поэтому и islink (), и isfile () могут быть истинными для одного и того же пути.
import os.path
os.path.isfile(fname)
если вам нужно убедиться, что это файл.
Начиная с Python 3.4, pathlib
модуль предлагает объектно-ориентированный подход (перенесенный pathlib2
в Python 2.7):
from pathlib import Path
my_file = Path("/path/to/file")
if my_file.is_file():
# file exists
Чтобы проверить каталог, выполните:
if my_file.is_dir():
# directory exists
Чтобы проверить, Path
существует ли объект независимо от того, является ли он файлом или каталогом, используйте exists()
:
if my_file.exists():
# path exists
Вы также можете использовать resolve(strict=True)
в try
блоке:
try:
my_abs_path = my_file.resolve(strict=True)
except FileNotFoundError:
# doesn't exist
else:
# exists
FileNotFoundError
было введено в Python 3. Если вам также необходимо поддерживать Python 2.7, а также Python 3, вы можете использоватьIOError
вместо него (какиеFileNotFoundError
подклассы) stackoverflow.com/a/21368457/1960959open('file', 'r+')
) и затем искать до конца.У вас есть
os.path.exists
функция:Это возвращает
True
как файлы, так и каталоги, но вместо этого вы можете использоватьпроверить, если это файл специально. Это следует за символическими ссылками.
источник
В отличие от
isfile()
,exists()
вернетсяTrue
за каталогами. В зависимости от того, хотите ли вы только простые файлы или каталоги, вы будете использоватьisfile()
илиexists()
. Вот простой вывод REPL:источник
источник
Используйте
os.path.isfile()
сos.access()
:источник
os.access()
вернет false.import os
, вам не нужноimport os.path
снова, так как он уже является частьюos
. Вам просто нужно импортировать,os.path
если вы собираетесь использовать функцииos.path
только изos
себя, а не из себя, чтобы импортировать меньшую вещь, но по мере использованияos.access
иos.R_OK
, второй импорт не нужен.источник
Хотя почти все возможные способы были перечислены в (по крайней мере, одном из) существующих ответов (например, добавлен материал, специфичный для Python 3.4 ), я постараюсь сгруппировать все вместе.
Примечание : каждый фрагмент кода стандартной библиотеки Python, который я собираюсь опубликовать, относится к версии 3.5.3 .
Постановка проблемы :
Возможные решения :
[Python 3]: os.path. существует ( путь ) (также проверить другие члены семьи функции , такие как
os.path.isfile
,os.path.isdir
,os.path.lexists
для слегка различных поведений)Все хорошо, но если следовать дереву импорта:
os.path
- posixpath.py ( ntpath.py )genericpath.py , строка ~ # 20 +
это просто блок try / исключением вокруг [Python 3]: os. stat ( путь, *, dir_fd = нет, follow_symlinks = True ) . Итак, ваш код попробуйте / за исключением бесплатного, но ниже в стеке фреймов есть (по крайней мере) один такой блок. Это относится и к другим функциям (в том числе
os.path.isfile
).1.1. [Python 3]: путь. is_file ()
Под капотом, это делает точно то же самое ( pathlib.py , линия ~ # 1330 ):
[Python 3]: с менеджерами контекста операторов . Или:
Создай:
И его использование - я повторю
os.path.isfile
поведение (обратите внимание, что это только для демонстрационных целей, не пытайтесь писать такой код для производства ):Используйте [Python 3]: contextlib. подавить ( * исключения ) - который был специально разработан для выборочного подавления исключений
Но, кажется, что они обертки за попытки / за исключением / еще / , наконец , блоки, так как [Python 3]: А с заявлением гласит:
Функции обхода файловой системы (и поиск результатов по соответствующим элементам)
[Python 3]: ос. listdir ( путь = '' ) (или [Python 3]:. ОС ScanDir ( '' = путь ) на Python против 3,5 + портировать: [PyPI]: ScanDir )
Под капотом оба используют:
через [GitHub]: python / cpython - (основной) cpython / Modules / posixmodule.c
os.listdir
(os.scandir
когда доступно)glob.glob
)os.listdir
Так как эти итерации по папкам, (в большинстве случаев) они неэффективны для нашей задачи (есть исключения, например , не символов подстановки Глоб Бинг - в @ShadowRanger указывал), так что я не буду настаивать на них. Не говоря уже о том, что в некоторых случаях может потребоваться обработка имени файла.
[Python 3]: ос. доступа ( путь, режим, *, dir_fd = None, effective_ids = False, follow_symlinks = True ) , поведение которых близка к
os.path.exists
( на самом деле это шире, в основном из - за 2 - й аргумент)os.access("/tmp", os.F_OK)
Так как я работаю в C , я использую этот метод, а потому , что под капотом, он вызывает нативный API s (опять же , с помощью «$ {} PYTHON_SRC_DIR /Modules/posixmodule.c» ), но он также открывает ворота для возможного пользователя ошибки , и это не так, как Python ic, как другие варианты. Итак, как правильно заметил @AaronHall, не используйте его, если не знаете, что делаете:
Примечание : вызов нативных API также возможен через [Python 3]: ctypes - библиотека сторонних функций для Python , но в большинстве случаев она более сложная.
( Зависит от Win ): поскольку vcruntime * ( msvcr * ) .dll также экспортирует семейство функций [MS.Docs]: _access, _waccess , вот пример:
Примечания :
os.F_OK
в вызове, но это только для ясности (его значение равно 0 )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) :__declspec(dllexport)
(почему на Земле обычный человек сделал бы это?), основная программа загружаема, но в значительной степени непригодна для использованияУстановите какой-нибудь сторонний модуль с возможностями файловой системы
Скорее всего, будет опираться на один из способов выше (возможно, с небольшими настройками).
Одним примером может быть (опять же, специфичный для Win ) [GitHub]: mhammond / pywin32 - расширения Python для Windows (pywin32) , которые являются оболочкой Python для WINAPI .
Но, поскольку это больше похоже на обходной путь, я остановлюсь здесь.
Другой ( слабый ) обходной путь ( gainarie ) - это (как я это называю) подход sysadmin : использование Python в качестве оболочки для выполнения команд оболочки
Победа :
Никс ( Lnx ( Убту )):
Итог :
Финальные заметки :
источник
glob.iglob
(иglob.glob
также) основаны наos.scandir
, так что теперь лениво; чтобы получить первый удар в каталоге из 10M файлов, вы сканируете только до первого попадания. И даже до 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:
Затем импортируйте его следующим образом:
источник
Предпочитаю оператор try. Это считается лучшим стилем и избегает условий гонки.
Не верь мне на слово. Есть много поддержки этой теории. Вот пара:
источник
try...except
не помогает решить эту проблему в любом случае.except:
предложение приведет к тому, что исключение, возникающее в этой части вашего кода, вызовет сбивающее с толку сообщение (вторая ошибка возникает во время обработка первого.)Теперь доступно начиная с 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
заявления, используяsuppress
менеджера контекста.Как избежать условий гонки без заявления о попытке:
suppress
Python 3.4 предоставляет нам
suppress
менеджер контекста (ранееignore
менеджер контекста), который выполняет семантически точно то же самое в меньшем количестве строк, в то же время (хотя бы внешне) встречая исходный запрос, чтобы избежатьtry
утверждения:Применение:
Для более ранних Питонов, вы можете бросить свои собственные
suppress
, но безtry
более подробного, чем с. Я действительно считаю, что на самом деле это единственный ответ, который не используетtry
ни на каком уровне Python, который может быть применен до Python 3.4, потому что вместо него используется менеджер контекста:Возможно, проще с попыткой:
Другие варианты, которые не отвечают запросу "без попытки":
ISFILE
из документов :
Но если вы изучите источник этой функции, вы увидите, что она действительно использует оператор try:
Все, что он делает, - использует заданный путь, чтобы посмотреть, сможет ли он получить статистику по нему, перехватить
OSError
и затем проверить, является ли это файл, если он не вызвал исключение.Если вы намереваетесь что-то сделать с файлом, я бы посоветовал напрямую попробовать его с попыткой, за исключением того, чтобы избежать условия гонки:
os.access
Доступно для Unix и Windows есть
os.access
, но для использования вы должны пройти флаги, и это не делает различий между файлами и каталогами. Это больше используется для проверки, имеет ли реальный вызывающий пользователь доступ в среде с повышенными привилегиями:Он также страдает от тех же проблем с расой, что и
isfile
. Из документов :Избегать использования
os.access
. Это функция низкого уровня, которая имеет больше возможностей для ошибок пользователя, чем объекты и функции более высокого уровня, описанные выше.Критика другого ответа:
Другой ответ говорит об этом
os.access
:Этот ответ говорит, что он предпочитает непифонический, подверженный ошибкам метод без объяснения причин. Похоже, это поощряет пользователей использовать низкоуровневые API, не понимая их.
Он также создает менеджер контекста, который, безоговорочно возвращая
True
, позволяет всем исключениям (включаяKeyboardInterrupt
иSystemExit
!) Проходить без вывода сообщений, что является хорошим способом скрыть ошибки.Это, кажется, поощряет пользователей принимать плохие методы.
источник
Импорт
os
облегчает навигацию и выполнение стандартных действий с вашей операционной системой.Для справки также см. Как проверить, существует ли файл с использованием Python?
Если вам нужны операции высокого уровня, используйте
shutil
.источник
os.path.exists
возвращает true для вещей, которые не являются файлами, например, для каталогов. Это дает ложные срабатывания. Смотрите другие ответы, которые рекомендуютos.path.isfile
.Тестирование файлов и папок с помощью
os.path.isfile()
,os.path.isdir()
иos.path.exists()
Предполагая, что «путь» является допустимым путем, эта таблица показывает, что возвращается каждой функцией для файлов и папок:
Вы также можете проверить, является ли файл файлом определенного типа, который используется
os.path.splitext()
для получения расширения (если вы его еще не знаете)источник
В 2016 году лучший способ все еще использует
os.path.isfile
:Или в Python 3 вы можете использовать
pathlib
:источник
pathlib
является ООП-решением Python для путей. Вы можете сделать намного больше с этим. Если вам просто нужно проверить существование, преимущество не так велико.Не похоже, что между try / кроме и есть существенная функциональная разница
isfile()
, поэтому вы должны использовать ту, которая имеет смысл.Если вы хотите прочитать файл, если он существует, выполните
Но если вы просто хотите переименовать файл, если он существует, и поэтому не нужно открывать его, выполните
Если вы хотите записать в файл, если он не существует, выполните
Если вам нужна блокировка файлов, это другое дело.
источник
os.path.exists
возвращает true для вещей, которые не являются файлами, например, для каталогов. Это дает ложные срабатывания. Смотрите другие ответы, которые рекомендуютos.path.isfile
.filepath
с правильным временем, и BAM перезаписывает целевой файл. Вы должны сделатьopen(filepath, 'wx')
вtry...except
блоке, чтобы избежать проблемы.OSError
еслиfilepath + '.old'
уже существует: «В Windows, если dst уже существует, OSError будет вызываться, даже если это файл; может быть невозможно реализовать атомарное переименование, когда dst называет существующий файл. "os.replace
переносимо выполняет автоматическую замену файла назначения (он идентиченos.rename
поведению Linux) (он только выдает ошибки, если имя назначения существует и является каталогом). Итак, вы застряли на 2.x, но у пользователей Py3 был хороший выбор уже несколько лет.rename
примере: это все еще должно быть сделано сtry
/except
.os.rename
(илиos.replace
на современном Python) является атомарным; проверка его, а затем переименование приводит к ненужной гонке и дополнительным системным вызовам. Просто сделайtry: os.replace(filepath, filepath + '.old') except OSError: pass
Вы можете попробовать это (безопаснее):
Результат будет:
Затем, в зависимости от результата, ваша программа может просто продолжать работать оттуда или вы можете написать код, чтобы остановить его, если хотите.
источник
try
Хотя я всегда рекомендую использовать
try
иexcept
заявления, вот несколько возможностей для вас (мой личный фаворит используетos.access
):Попробуйте открыть файл:
Открытие файла всегда проверяет его наличие. Вы можете сделать функцию так:
Если это значение False, оно прекратит выполнение с неуправляемым IOError или OSError в более поздних версиях Python. Чтобы поймать исключение, вы должны использовать предложение try, кроме. Конечно, вы всегда можете использовать
try
выражение "исключение" вот так (спасибо hsandt за то, что заставил меня задуматься):использование
os.path.exists(path)
:Это проверит наличие того, что вы укажете. Тем не менее, он проверяет файлы и каталоги, поэтому будьте осторожны с тем, как вы его используете.
использование
os.access(path, mode)
:Это проверит, есть ли у вас доступ к файлу. Он проверит разрешения. На основании документации os.py, введя
os.F_OK
его, он проверит наличие пути. Однако использование этого создаст дыру в безопасности, поскольку кто-то может атаковать ваш файл, используя время между проверкой прав доступа и открытием файла. Вместо этого вам следует перейти непосредственно к открытию файла вместо проверки его прав доступа. ( ЭСПЦ против LBYP ). Если вы не собираетесь открывать файл впоследствии, а только проверяете его существование, то вы можете использовать это.Во всяком случае, здесь:
Я должен также упомянуть, что есть два способа, которыми вы не сможете проверить существование файла. Либо проблема будет,
permission denied
либоno such file or directory
. Если вы пойметеIOError
, установитеIOError as e
(как мой первый вариант), а затем введите,print(e.args)
чтобы вы могли надеяться определить вашу проблему. Я надеюсь, что это помогает! :)источник
Дата: 2017-12-04
Каждое возможное решение было указано в других ответах.
Интуитивно понятный и спорный способ проверить, существует ли файл, заключается в следующем:
Я сделал исчерпывающую таблицу для вашей справки:
источник
Если файл предназначен для открытия, вы можете использовать один из следующих методов:
ОБНОВИТЬ
Просто чтобы избежать путаницы и основываясь на полученных мной ответах, текущий ответ находит либо файл, либо каталог с заданным именем.
источник
os.path.exists
возвращает true для вещей, которые не являются файлами, например, для каталогов. Это дает ложные срабатывания. Смотрите другие ответы, которые рекомендуютos.path.isfile
.Дополнительно
os.access()
:Быть
R_OK
,W_OK
иX_OK
флаги для проверки разрешений ( doc ).источник
SRC: http://www.pfinn.net/python-check-if-file-exists.html
источник
Если вы импортировали NumPy уже для других целей , то нет необходимости импортировать другие библиотеки , как
pathlib
,os
,paths
и т.д.Это вернет истину или ложь в зависимости от его существования.
источник
Вы можете написать предложение Брайана без
try:
.suppress
является частью Python 3.4. В старых версиях вы можете быстро написать свой собственный подавитель:источник
Я являюсь автором пакета, который существует уже около 10 лет, и у него есть функция, которая решает этот вопрос напрямую. В основном, если вы работаете не в системе Windows, она использует
Popen
для доступаfind
. Тем не менее, если вы находитесь в Windows, он копируетfind
с эффективным обходчиком файловой системы.Сам код не использует
try
блок ... за исключением определения операционной системы и, следовательно,find
перехода к стилю «Unix» или «hand-buillt»find
. Временные тесты показали, чтоtry
определение ОС было быстрее, поэтому я использовал ее там (но больше нигде).И документ ...
Реализация, если вам интересно посмотреть, здесь: https://github.com/uqfoundation/pox/blob/89f90fb308f285ca7a62eabe2c38acb87e89dad9/pox/shutils.py#L190
источник
Проверьте, существует ли файл или каталог
Вы можете следовать этим трем путям:
источник
Добавление еще одного небольшого изменения, которое не совсем отражено в других ответах.
Это будет обрабатывать случай
file_path
существаNone
или пустую строку.Добавление варианта на основе предложения от Шахбаз
Добавление варианта на основе предложения от Питера Вуда
источник
if (x) return true; else return false;
это действительно простоreturn x
. Ваши последние четыре строки могут статьreturn os.path.isfile(file_path)
. Пока мы на этом, вся функция может быть упрощена какreturn file_path and os.path.isfile(file_path)
.return x
в случаеif (x)
. Python будет рассматривать пустую строку False, в этом случае мы будем возвращать пустую строку вместо bool. Цель этой функции - всегда возвращать bool.x
этоos.path.isfile(..)
так уже BOOL.os.path.isfile(None)
вызывает исключение, поэтому я добавил проверку if. Я мог бы, вероятно, просто обернуть это в попытку / за исключением, но я чувствовал, что это было более явно таким образом.return file_path and os.path.isfile(file_path)
Вот 1-строчная команда Python для среды командной строки Linux. Я нахожу это ОЧЕНЬ ХЕНДИ, так как я не такой горячий парень из Баш
Я надеюсь, что это полезно.
источник
[ -f "${file}" ] && echo "file found" || echo "file not found"
(что совпадает сif [ ... ]; then ...; else ...; fi
).Вы можете использовать библиотеку "OS" Python:
источник
os.path.exists
возвращает true для вещей, которые не являются файлами, например, для каталогов. Это дает ложные срабатывания. Смотрите другие ответы, которые рекомендуютos.path.isfile
.exists
это нормально. Если цель состоит в том, чтобы определить, безопасно ли открывать предположительно существующий файл, то критика оправдана и существует недостаточно точно. К сожалению, ОП не определяет, какая цель является желаемой (и, вероятно, больше не будет).В 2016 году это все еще возможно самый простой способ проверить, существует ли файл и есть ли он:
isfile
на самом деле просто вспомогательный метод, который используется внутриos.stat
иstat.S_ISREG(mode)
снизу. Этоos.stat
низкоуровневый метод, который предоставит вам подробную информацию о файлах, каталогах, сокетах, буферах и многом другом. Больше о os.stat здесьПримечание. Однако этот подход никоим образом не блокирует файл, и поэтому ваш код может стать уязвимым для « времени проверки ко времени использования » ( TOCTTOU ).
Поэтому повышение исключений считается приемлемым и питонским подходом для управления потоком в вашей программе. И нужно рассмотреть обработку отсутствующих файлов с ошибками ввода-вывода, а не
if
заявлениями ( просто совет ).источник
источник
isReadableFile(path,fileName)
вернется,True
если файл доступен и читается процессом \ program \ thread