Как мне проверить, существует ли файл, без использования оператора try?
30 ответов
Используйте os.path.isfile()
< / a> с os.access()
а>:
import os
PATH = './file.txt'
if os.path.isfile(PATH) and os.access(PATH, os.R_OK):
print("File exists and is readable")
else:
print("Either the file is missing or not readable")
os.access()
вернет false.
import os
, вам не нужно снова import os.path
, поскольку он уже является частью os
. Вам просто нужно импортировать os.path
, если вы собираетесь использовать функции только из os.path
, а не из самого os
, чтобы импортировать более мелкую вещь, но когда вы используете os.access
и os.R_OK
, второй импорт не нужен.
import os
os.path.exists(path) # Returns whether the path (directory or file) exists or not
os.path.isfile(path) # Returns whether the file exists or not
Хотя почти все возможные способы были перечислены в (по крайней мере, в одном из) существующих ответов (например, был добавлен конкретный материал для Python 3.4 ), я постараюсь сгруппировать все вместе.
Примечание : каждый фрагмент кода стандартной библиотеки Python , который я собираюсь опубликовать, принадлежит версии 3.5.3 .
Описание проблемы :
- Проверить наличие файла ( спорного : также папки ("особого" файла)?)
- Не используйте try / except / else / finally блоки
Возможные решения :
[Python 3]: os.path. существует ( путь ) (также проверьте другие члены семейства функций, такие как
os.path.isfile
,os.path.isdir
,os.path.lexists
, на предмет немного отличающегося поведения)os.path.exists(path)
Вернуть
True
, если путь относится к существующему пути или дескриптору открытого файла. ВозвращаетFalse
для неработающих символических ссылок. На некоторых платформах эта функция может возвращатьFalse
, если не предоставлено разрешение на выполнение os.stat () в запрошенном файле, даже если путь физически существует.Все хорошо, но если следовать дереву импорта:
-
os.path
- posixpath.py ( ntpath.py )-
genericpath.py , строка ~ # 20 +
существует def (путь): "" "Проверить, существует ли путь. Возвращает False для неработающих символических ссылок" "" пытаться: st = os.stat (путь) кроме os.error: вернуть ложь вернуть True
-
это просто блок try / except вокруг [Python 3]: os. stat ( путь, *, dir_fd = None, follow_symlinks = True < / em>). Итак, ваш код попробуйте / за исключением бесплатен, но ниже в стеке кадров есть (по крайней мере) один такой блок. Это также относится к другим функциям ( включая
os.path.isfile
).1.1. [Python 3]: путь. is_file ()
- Это более изящный (и более python ic) способ обработки путей, но
-
Под капотом он делает в точности то же самое ( pathlib.py , строка ~ # 1330 ): p>
def is_file (self): "" " Является ли этот путь обычным файлом (также True для символических ссылок, указывающих в обычные файлы). "" " пытаться: вернуть S_ISREG (self.stat (). st_mode) кроме OSError как e: если e.errno отсутствует в (ENOENT, ENOTDIR): поднимать # Путь не существует или символическая ссылка не работает # (см. https://bitbucket.org/pitrou/pathlib/issue/12/) вернуть ложь
-
[Python 3]: с менеджерами контекста операторов. Или:
-
Создать:
class Swallow: # Пустой пример swallowed_exceptions = (FileNotFoundError,) def __enter __ (сам): print ("Вход ...") def __exit __ (self, exc_type, exc_value, exc_traceback): print ("Выход:", exc_type, exc_value, exc_traceback) return exc_type в Swallow.swallowed_exceptions # только проглатывать FileNotFoundError (не, например, TypeError - если пользователь передает неверный аргумент, например None или float или ...)
-
И его использование - я воспроизведу поведение
os.path.isfile
(обратите внимание, что это просто для демонстрации, не пытайтесь написать такой код для производственной ):импорт ОС статистика импорта def isfile_seaman (путь): # Dummy func результат = Ложь с Swallow (): результат = stat.S_ISREG (os.stat (путь) .st_mode) вернуть результат
-
-
Используйте [Python 3]: contextlib. подавить ( * исключения ) - который был специально разработан для выборочного подавления исключений
Но они кажутся обертками над попыткой / за исключением / else / finally блокируется как [Python 3]: в инструкции with говорится:Это позволяет обычно попробовать... except... finally шаблоны использования, которые необходимо инкапсулировать для удобного повторного использования.
-
Функции обхода файловой системы (и поиск в результатах соответствующих элементов)
-
[Python 3]: os. listdir ( path = '.' ) (или [Python 3]: os. scandir ( path = '.' ) на Python v 3.5 +, backport: [PyPI]: scandir)
-
Под капотом оба используют:
- Nix : [man7]: OPENDIR (3) / [man7]: READDIR (3) < / a> / [man7]: CLOSEDIR (3) < / li>
- Win : [MS.Docs]: функция FindFirstFileW / [MS.Docs]: функция FindNextFileW / [MS.Docs]: функция FindClose
через [GitHub]: python / cpython - (master) cpython / Модули / posixmodule.c
Использование scandir () вместо listdir () может значительно повысить производительность кода, которому также нужен тип файла или файл. информацию об атрибутах, поскольку объекты os.DirEntry предоставляют эту информацию, если операционная система предоставляет его при сканировании каталога. Все методы os.DirEntry могут выполнять системный вызов, но < a href = "https://docs.python.org/3/library/os.html#os.DirEntry.is_dir" rel = "noreferrer"> is_dir () и is_file () обычно требует системного вызова только для символьных ссылок; os.DirEntry.stat () всегда требует наличия системы вызывает Unix, но требует только одну для символьных ссылок в Windows.
-
- [Python 3]: os. walk ( top, topdown = True, onerror = None, followlinks = False )
- Используется
os.listdir
(os.scandir
, если доступно)
- Используется
- [Python 3]: glob. iglob ( pathname, *, recursive = False ) (или его предшественник:
glob.glob
)- Сама по себе функция обхода не кажется (по крайней мере, в некоторых случаях), но она все еще использует
os.listdir
- Сама по себе функция обхода не кажется (по крайней мере, в некоторых случаях), но она все еще использует
Поскольку они перебирают папки (в большинстве случаев), они неэффективны для нашей проблемы (есть исключения, такие как glob bing без подстановочных знаков - как указал @ShadowRanger), поэтому я Я не собираюсь на них настаивать. Не говоря уже о том, что в некоторых случаях может потребоваться обработка имени файла.-
[Python 3]: os. доступ (< em> path, mode, *, dir_fd = None, effective_ids = False, follow_symlinks = True ), поведение которого близко к
os.path.exists
(на самом деле оно шире, в основном из-за 2 nd аргумент)- разрешения пользователя могут ограничивать "видимость" файла, как указано в документе: <цитата>
... проверить, имеет ли вызывающий пользователь указанный доступ к пути . режим должен быть F_OK для тестирования наличие пути ...
os.access("/tmp", os.F_OK)
Поскольку я также работаю на C , я также использую этот метод, потому что внутри он вызывает собственные API (опять же, через "$ {PYTHON_SRC_DIR} /Modules/posixmodule.c" ), но он также открывает ворота для возможных ошибок пользователя , а не как Python ic как и другие варианты. Итак, как справедливо заметил @AaronHall, не используйте его, если не знаете, что делаете:
- Nix : [man7]: ДОСТУП (2) (!!! обратите внимание на примечание о дыре в безопасности , которую может вызвать его использование !!!)
- Win : [MS.Docs]: функция GetFileAttributesW
Примечание : вызов собственных API также возможен через [Python 3]: ctypes - библиотека сторонних функций для Python, но в большинстве случаев она более сложная.
( Win ): поскольку vcruntime * ( msvcr * ) .dll экспортирует a [MS.Docs ]: _access, _waccess, а также семейство функций, вот пример:
Python 3.5.3 (v3.5.3: 1880cb95a742, 16 января 2017 г., 16:02:32) [MSC v.1900, 64 бит (AMD64)] на win32 Для получения дополнительной информации введите «помощь», «авторские права», «кредиты» или «лицензия». >>> import os, ctypes >>> ctypes.CDLL ("msvcrt") ._ waccess (u "C: \\ Windows \\ System32 \\ cmd.exe", os.F_OK) 0 >>> ctypes.CDLL ("msvcrt") ._ waccess (u "C: \\ Windows \\ System32 \\ cmd.exe.notexist", os.F_OK) -1
Примечания :
- Хотя это не очень хорошая практика, я использую
os.F_OK
в вызове, но это просто для ясности (его значение - 0 ) - Я использую _waccess , чтобы один и тот же код работал на Python3 и Python2 (несмотря на unicode связанные различия между ними)
- Хотя это нацелено на очень конкретную область, об этом не упоминалось ни в одном из предыдущих ответов
Аналог Lnx ( Ubtu (16 x64) ):Python 3.5.2 (по умолчанию, 17 ноября 2016 г., 17:05:23) [GCC 5.4.0 20160609] в Linux Для получения дополнительной информации введите «помощь», «авторские права», «кредиты» или «лицензия». >>> import os, ctypes >>> ctypes.CDLL ("/ lib / x86_64-linux-gnu / libc.so.6"). access (b "/ tmp", os.F_OK) 0 >>> ctypes.CDLL ("/ lib / x86_64-linux-gnu / libc.so.6"). access (b "/tmp.notexist", os.F_OK) -1
Примечания :
-
Вместо жесткого кодирования пути libc ( "/lib/x86_64-linux-gnu/libc.so.6" ), который может (и, скорее всего, , будет) варьироваться в зависимости от системы, Нет (или пустую строку) можно передать в конструктор CDLL (
ctypes.CDLL(None).access(b"/tmp", os.F_OK)
). Согласно [man7]: DLOPEN (3): p> <цитата>Если filename имеет значение 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) Extensions, который является оболочкой Python над WINAPI .Но, поскольку это больше похоже на обходной путь, я останавливаюсь на этом.
Другой (неубедительный) обходной путь ( gainarie ) - это (как я люблю его называть) подход sysadmin : используйте Python в качестве оболочки для выполнения команды оболочки
-
Победа :
<цитата>(py35x64_test) e: \ Work \ Dev \ StackOverflow \ q000082831> "e: \ Work \ Dev \ VEnvs \ py35x64_test \ Scripts \ python.exe" -c "import os; print (os.system ('dir / b \" C: \\ Windows \\ System32 \\ cmd.exe \ "> nul 2> & 1'))» 0 (py35x64_test) e: \ Work \ Dev \ StackOverflow \ q000082831> "e: \ Work \ Dev \ VEnvs \ py35x64_test \ Scripts \ python.exe" -c "import os; print (os.system ('dir / b \" C: \\ Windows \\ System32 \\ cmd.exe.notexist \ "> nul 2> & 1 '))" 1
-
Nix ( Lnx ( Ubtu )):
<цитата>[cfati @ cfati-ubtu16x64-0: ~]> python3 -c "import os; print (os.system ('ls \" / tmp \ "> / dev / null 2> & 1 ')) " 0 [cfati @ cfati-ubtu16x64-0: ~]> python3 -c "import os; print (os.system ('ls \" / tmp.notexist \ "> / dev / null 2> & 1'))" 512
-
Итог :
- Используйте try / except / else em> / finally , потому что они могут предотвратить ряд неприятных проблем. Противоположным примером, который я могу придумать, является производительность: такие блоки являются дорогостоящими, поэтому старайтесь не помещать их в код, который должен запускаться сотни тысяч раз в секунду (но поскольку (в большинстве случаев) это связано с доступом к диску, это не так).
Заключительные примечания :
- Я постараюсь поддерживать его в актуальном состоянии, любые предложения приветствуются, я включу все полезное, что появится в ответе
glob.glob
, вам определенно не нужно os.scandir
командовать вами.
os.path.isdir
или os.path.lexist
, поскольку это набор вызовов функций уровня Python и строковых операций, прежде чем он решит, что эффективный путь жизнеспособен, но без дополнительных системных вызовов или операций ввода-вывода, которые на порядки медленнее).
Это самый простой способ проверить, существует ли файл. Просто потому что файл существовал, когда вы установили флажок, не гарантирует , что он будет там, когда вам нужно будет его открыть.
import os
fname = "foo.txt"
if os.path.isfile(fname):
print("file does exist at this time")
else:
print("no such file exists at this time")
Python 3.4+ имеет объектно-ориентированный модуль пути: pathlib . Используя этот новый модуль, вы можете проверить, существует ли такой файл:
import pathlib
p = pathlib.Path('path/to/file')
if p.is_file(): # or p.is_dir() to see if it is a directory
# do stuff
Вы можете (и обычно должны) использовать блок try/except
при открытии файлов:
try:
with p.open() as f:
# do awesome stuff
except OSError:
print('Well darn.')
В модуле pathlib есть много интересных вещей: удобная подстановка подстановки, проверка владельца файла, более легкое объединение путей и т. Д. Это стоит проверить. Если вы используете более старый Python (версия 2.6 или новее), вы все равно можете установить pathlib с помощью pip:
# installs pathlib2 on older Python versions
# the original third-party module, pathlib, is no longer maintained.
pip install pathlib2
Затем импортируйте его следующим образом:
# Older Python versions
import pathlib2 as pathlib
Предпочитайте заявление о попытке. Это считается лучшим стилем и позволяет избежать условий гонки.
Не верьте мне на слово. Эта теория имеет множество подтверждений. Вот парочка:
- Стиль: Раздел «Обработка необычных условий» страницы http://allendowney.com/sd/notes/notes11. txt
- Избегание условий гонки
try...except
не помогает решить эту проблему.
except:
приведет к тому, что исключение, возникающее в этой части вашего кода, вызовет сбивающее с толку сообщение (вторая ошибка возникла при обработке первой.)
Как проверить, существует ли файл, с помощью Python без использования оператора try?
Теперь, доступный начиная с Python 3.4, импортируйте и создайте экземпляр объекта Path
с именем файла и проверьте метод is_file
(обратите внимание, что он также возвращает True для символических ссылок, указывающих на обычные файлы):
>>> from pathlib import Path
>>> Path('/').is_file()
False
>>> Path('/initrd.img').is_file()
True
>>> Path('/doesnotexist').is_file()
False
Если вы используете Python 2, вы можете выполнить обратный перенос модуля pathlib из pypi, pathlib2
a> или иным образом проверьте isfile
из модуля os.path
:
>>> import os
>>> os.path.isfile('/')
False
>>> os.path.isfile('/initrd.img')
True
>>> os.path.isfile('/doesnotexist')
False
Вышеупомянутое, вероятно, является лучшим прагматичным прямым ответом здесь, но есть вероятность состояния гонки (в зависимости от того, что вы пытаетесь выполнить), и тот факт, что базовая реализация использует try
, но Python использует try
везде в его реализации.
Поскольку Python повсюду использует try
, на самом деле нет причин избегать реализации, которая его использует.
Но остальная часть этого ответа пытается учесть эти предостережения.
Более длинный и педантичный ответ
Доступен начиная с Python 3.4, используйте новый объект Path
в pathlib
. Обратите внимание, что .exists
не совсем верно, потому что каталоги не являются файлами (кроме unix-смысла, что все является файлом).
>>> from pathlib import Path
>>> root = Path('/')
>>> root.exists()
True
Итак, нам нужно использовать is_file
:
>>> root.is_file()
False
Вот справка по is_file
:
is_file(self)
Whether this path is a regular file (also True for symlinks pointing
to regular files).
Итак, давайте получим файл, который, как мы знаем, является файлом:
>>> import tempfile
>>> file = tempfile.NamedTemporaryFile()
>>> filepathobj = Path(file.name)
>>> filepathobj.is_file()
True
>>> filepathobj.exists()
True
По умолчанию NamedTemporaryFile
удаляет файл при закрытии (и автоматически закрывается, когда на него больше не существует ссылок).
>>> del file
>>> filepathobj.exists()
False
>>> filepathobj.is_file()
False
Однако если вы углубитесь в реализацию, вы увидим, что is_file
использует try
:
def is_file(self):
"""
Whether this path is a regular file (also True for symlinks pointing
to regular files).
"""
try:
return S_ISREG(self.stat().st_mode)
except OSError as e:
if e.errno not in (ENOENT, ENOTDIR):
raise
# Path doesn't exist or is a broken symlink
# (see https://bitbucket.org/pitrou/pathlib/issue/12/)
return False
Условия гонки: почему нам нравится пробовать
Нам нравится try
, потому что он позволяет избежать условий гонки. С try
вы просто пытаетесь прочитать ваш файл, ожидая, что он там есть, а если нет, вы перехватываете исключение и выполняете любое резервное поведение, которое имеет смысл.
Если вы хотите проверить, существует ли файл, прежде чем пытаться его прочитать, и вы, возможно, удаляете его, а затем используете несколько потоков или процессов, или другая программа знает об этом файле и может его удалить - вы рискуете состояние гонки , если вы проверяете, что оно существует, потому что вы затем участвуете в гонке , чтобы открыть его до того, как его состояние (его существование) изменится.
Условия гонки очень трудно отлаживать, потому что есть очень маленькое окно, в котором они могут привести к сбою вашей программы.
Но если это ваша мотивация, вы можете получить значение оператора try
с помощью диспетчера контекста suppress
.
Избежание условий гонки без оператора try: suppress
Python 3.4 предоставляет нам suppress
контекстный менеджер ( ранее это был ignore
диспетчер контекста), который семантически делает то же самое в меньшем количестве строк, тогда как также (по крайней мере, поверхностно) отвечая на исходную просьбу избегать утверждения try
:
from contextlib import suppress
from pathlib import Path
Применение:
>>> with suppress(OSError), Path('doesnotexist').open() as f:
... for line in f:
... print(line)
...
>>>
>>> with suppress(OSError):
... Path('doesnotexist').unlink()
...
>>>
Для более ранних версий Pythons вы могли использовать собственный suppress
, но без try
будет более подробным, чем с. Я верю, что это на самом деле единственный ответ, который не использует try
ни на одном уровне в Python , который может быть применен к более ранним версиям Python 3.4, потому что вместо этого он использует диспетчер контекста:
class suppress(object):
def __init__(self, *exceptions):
self.exceptions = exceptions
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
if exc_type is not None:
return issubclass(exc_type, self.exceptions)
Возможно, проще попробовать:
from contextlib import contextmanager
@contextmanager
def suppress(*exceptions):
try:
yield
except exceptions:
pass
Другие варианты, которые не соответствуют запросу «без попытки»:
isfile
import os
os.path.isfile(path)
Из документов:
os.path.isfile(path)
Верните True, если путь - существующий обычный файл. Это следует за символическим ссылки, поэтому и
islink()
, иisfile()
могут быть истинными для одного и того же пути.
Но если вы изучите источник этой функции, вы Увидим, что он действительно использует оператор try:
# This follows symbolic links, so both islink() and isdir() can be true # for the same path on systems that support symlinks def isfile(path): """Test whether a path is a regular file""" try: st = os.stat(path) except os.error: return False return stat.S_ISREG(st.st_mode)
>>> OSError is os.error
True
Все, что он делает, это использует заданный путь, чтобы увидеть, может ли он получить статистику по нему, перехватывает OSError
и затем проверяет, является ли это файлом, если он не вызывает исключение.
Если вы собираетесь что-то сделать с файлом, я бы посоветовал напрямую попробовать это с помощью try, за исключением того, чтобы избежать состояния гонки:
try:
with open(path) as f:
f.read()
except OSError:
pass
os.access
Для Unix и Windows доступен os.access
, но для использования вы должны передавать флаги, и он не делает различий между файлами и каталогами. Это больше используется для проверки, имеет ли реальный вызывающий пользователь доступ в среде с повышенными привилегиями:
import os
os.access(path, os.F_OK)
Он также страдает теми же проблемами состояния гонки, что и isfile
. Из документов:
Примечание. Используя access (), чтобы проверить, авторизован ли пользователь, например, открытие файла до того, как это сделать, с помощью open () создает брешь в безопасности, потому что пользователь может использовать короткий промежуток времени между проверкой и открытием файла, чтобы манипулировать им. Предпочтительно использовать методы EAFP. Например:
if os.access("myfile", os.R_OK): with open("myfile") as fp: return fp.read() return "some default data"
лучше записать как:
try: fp = open("myfile") except IOError as e: if e.errno == errno.EACCES: return "some default data" # Not a permission error. raise else: with fp: return fp.read()
Избегайте использования os.access
. Это функция низкого уровня, которая имеет больше возможностей для ошибки пользователя, чем объекты и функции более высокого уровня, описанные выше.
Критика другого ответа:
Другой ответ говорит о os.access
:
Лично я предпочитаю этот, потому что под капотом он вызывает собственные API (через "$ {PYTHON_SRC_DIR} /Modules/posixmodule.c"), но он также открывает ворота для возможных ошибок пользователя, и он не такой Pythonic, как другие варианты. :
В этом ответе говорится, что он предпочитает не-питонический, подверженный ошибкам метод без каких-либо оснований. Кажется, это побуждает пользователей использовать низкоуровневые API, не понимая их.
Он также создает диспетчер контекста, который, безоговорочно возвращая True
, позволяет всем Исключениям (включая KeyboardInterrupt
и SystemExit
!) Проходить без уведомления, что является хорошим способом скрыть ошибки.
Похоже, это побуждает пользователей применять неэффективные методы.
import os
#Your path here e.g. "C:\Program Files\text.txt"
#For access purposes: "C:\\Program Files\\text.txt"
if os.path.exists("C:\..."):
print "File found!"
else:
print "File not found!"
Импорт os
упрощает навигацию и выполнение стандартных действий с вашей операционной системой.
Для справки также см. Как проверить, существует ли файл с помощью Python?
Если вам нужны высокоуровневые операции, используйте shutil
.
os.path.exists
возвращает истину для вещей, которые не являются файлами, например каталогов. Это дает ложные срабатывания. См. Другие ответы, рекомендующие os.path.isfile
.
Проверка файлов и папок с помощью os.path.isfile()
, os.path.isdir()
и os.path.exists()
Предполагая, что «путь» является допустимым путем, в этой таблице показано, что возвращает каждая функция для файлов и папок:
Вы также можете проверить, является ли файл определенным типом файла, используя os.path.splitext()
, чтобы получить расширение (если вы его еще не знаете)
>>> import os
>>> path = "path to a word document"
>>> os.path.isfile(path)
True
>>> os.path.splitext(path)[1] == ".docx" # test if the extension is .docx
True
В 2016 году лучшим способом по-прежнему остается использование os.path.isfile
:
>>> os.path.isfile('/path/to/some/file.txt')
Или в Python 3 вы можете использовать pathlib
:
import pathlib
path = pathlib.Path('/path/to/some/file.txt')
if path.is_file():
...
pathlib
- это ООП-решение Python для путей. Вы можете сделать с ним гораздо больше. Если вам просто нужно проверить наличие, преимущество не так велико.
Не похоже, что есть значимая функциональная разница между try / except и isfile()
, поэтому вам следует использовать то, что имеет смысл.
Если вы хотите прочитать файл, если он существует, выполните
try:
f = open(filepath)
except IOError:
print 'Oh dear.'
Но если вы просто хотите переименовать файл, если он существует, и, следовательно, вам не нужно его открывать, выполните
if os.path.isfile(filepath):
os.rename(filepath, filepath + '.old')
Если вы хотите записать в файл, если он не существует, выполните
# python 2
if not os.path.isfile(filepath):
f = open(filepath, 'w')
# python 3, x opens for exclusive creation, failing if the file already exists
try:
f = open(filepath, 'wx')
except IOError:
print 'file already exists'
Другое дело, если вам нужна блокировка файлов.
os.path.exists
возвращает истину для вещей, которые не являются файлами, например каталогов. Это дает ложные срабатывания. См. Другие ответы, рекомендующие 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:
# http://effbot.org/zone/python-with-statement.htm
# 'with' is safer to open a file
with open('whatever.txt') as fh:
# Do something with 'fh'
except IOError as e:
print("({})".format(e))
Выход будет:
([Errno 2] Нет такого файла или каталога: 'any.txt')
Затем, в зависимости от результата, ваша программа может просто продолжать работать оттуда или вы можете закодировать, чтобы остановить ее, если хотите.
try
Хотя я всегда рекомендую использовать операторы try
и except
, вот несколько возможностей для вас (я лично предпочитаю использовать os.access
):
Попробуйте открыть файл:
Открытие файла всегда проверяет его существование. Вы можете сделать функцию так:
def File_Existence(filepath): f = open(filepath) return True
Если значение равно False, выполнение будет остановлено с необработанной ошибкой IOError. или OSError в более поздних версиях Python. Чтобы поймать исключение, вы должны использовать предложение try except. Конечно вы всегда можете используйте оператор
try
except` вроде этого (спасибо hsandt за то, что заставил задуматься):def File_Existence(filepath): try: f = open(filepath) except IOError, OSError: # Note OSError is for later versions of Python return False return True
Используйте
os.path.exists(path)
:Это проверит наличие того, что вы указали. Однако он проверяет файлы и в каталогах, поэтому будьте осторожны с тем, как вы его используете.
import os.path >>> os.path.exists("this/is/a/directory") True >>> os.path.exists("this/is/a/file.txt") True >>> os.path.exists("not/a/directory") False
Используйте
os.access(path, mode)
:Это проверит, есть ли у вас доступ к файлу. Он проверит разрешения. На основе документации os.py, набрав
os.F_OK
, он проверит существование пути. Однако использование этого создаст брешь в безопасности, поскольку кто-то может атаковать ваш файл, используя время между проверкой разрешений и открытием файла. Вместо этого вам следует перейти непосредственно к открытию файла, а не проверять его разрешения. (EAFP против LBYP). Если вы не собираетесь открывать файл после этого, а только проверяете его существование, вы можете использовать это.Во всяком случае, здесь:
>>> import os >>> os.access("/is/a/file.txt", os.F_OK) True
Я также должен упомянуть, что есть два способа, которыми вы не сможете проверить существование файла. Либо проблема будет permission denied
, либо no such file or directory
. Если вы поймали IOError
, установите IOError as e
(как и мой первый вариант), а затем введите print(e.args)
, чтобы вы могли, надеюсь, определить свою проблему. Я надеюсь, что это помогает! :)
Дата: 2017-12-04
Все возможные решения перечислены в других ответах.
Интуитивно понятный и аргументированный способ проверить, существует ли файл, заключается в следующем:
import os
os.path.isfile('~/file.md') # Returns True if exists, else False
# additionaly check a dir
os.path.isdir('~/folder') # Returns True if the folder exists, else False
# check either a dir or a file
os.path.exists('~/file')
Я сделал для вас исчерпывающую шпаргалку:
#os.path methods in exhaustive cheatsheet
{'definition': ['dirname',
'basename',
'abspath',
'relpath',
'commonpath',
'normpath',
'realpath'],
'operation': ['split', 'splitdrive', 'splitext',
'join', 'normcase'],
'compare': ['samefile', 'sameopenfile', 'samestat'],
'condition': ['isdir',
'isfile',
'exists',
'lexists'
'islink',
'isabs',
'ismount',],
'expand': ['expanduser',
'expandvars'],
'stat': ['getatime', 'getctime', 'getmtime',
'getsize']}
Дополнительно os.access()
:
if os.access("myfile", os.R_OK):
with open("myfile") as fp:
return fp.read()
Будучи R_OK
, W_OK
и X_OK
флагами для проверки разрешений (doc).
Если вы уже импортировали NumPy для других целей, тогда нет необходимости импортировать другие библиотеки, такие как pathlib
, os
, paths
и т. Д.
import numpy as np
np.DataSource().exists("path/to/your/file")
Это вернет истину или ложь в зависимости от его существования.
Вы можете написать предложение Брайана без try:
.
from contextlib import suppress
with suppress(IOError), open('filename'):
process()
suppress
является частью Python 3.4. В более старых версиях вы можете быстро написать собственное подавление:
from contextlib import contextmanager
@contextmanager
def suppress(*exceptions):
try:
yield
except exceptions:
pass
Я являюсь автором пакета, который существует уже около 10 лет, и в нем есть функция, которая напрямую решает этот вопрос. Обычно, если вы работаете в системе, отличной от Windows, она использует Popen
для доступа к find
. Однако, если вы работаете в Windows, он реплицирует find
с помощью эффективного обходчика файловой системы.
Сам код не использует блок try
... кроме определения операционной системы и, таким образом, направляет вас к "Unix" -стилю find
или ручному построению find
. Временные тесты показали, что try
быстрее определяет ОС, поэтому я использовал одну из них (но больше нигде).
>>> import pox
>>> pox.find('*python*', type='file', root=pox.homedir(), recurse=False)
['/Users/mmckerns/.python']
И документ…
>>> print pox.find.__doc__
find(patterns[,root,recurse,type]); Get path to a file or directory
patterns: name or partial name string of items to search for
root: path string of top-level directory to search
recurse: if True, recurse down from root directory
type: item filter; one of {None, file, dir, link, socket, block, char}
verbose: if True, be a little verbose about the search
On some OS, recursion can be specified by recursion depth (an integer).
patterns can be specified with basic pattern matching. Additionally,
multiple patterns can be specified by splitting patterns with a ';'
For example:
>>> find('pox*', root='..')
['/Users/foo/pox/pox', '/Users/foo/pox/scripts/pox_launcher.py']
>>> find('*shutils*;*init*')
['/Users/foo/pox/pox/shutils.py', '/Users/foo/pox/pox/__init__.py']
>>>
Реализация, если вы хотите посмотреть, находится здесь: https://github.com/uqfoundation/898ec/898ec8c8e8c8e8c8e8c8e8e8e8d08e8e8e8e8b8e6 /pox/shutils.py#L190
Убедитесь, что файл или каталог существует
Вы можете воспользоваться этими тремя способами:
Примечание 1.
os.path.isfile
используется только для файлов
import os.path
os.path.isfile(filename) # True if file exists
os.path.isfile(dirname) # False if directory exists
Примечание 2:
os.path.exists
используется как для файлов, так и для каталогов.
import os.path
os.path.exists(filename) # True if file exists
os.path.exists(dirname) #True if directory exists
Метод
pathlib.Path
(включен в Python 3+, устанавливается с помощью pip для Python 2)
from pathlib import Path
Path(filename).exists()
Добавление еще одного небольшого изменения, которое не совсем отражено в других ответах.
Это будет обрабатывать случай, когда file_path
является None
или пустой строкой.
def file_exists(file_path):
if not file_path:
return False
elif not os.path.isfile(file_path):
return False
else:
return True
Добавление варианта на основе предложения Шахбаза
def file_exists(file_path):
if not file_path:
return False
else:
return os.path.isfile(file_path)
Добавление варианта на основе предложения Питера Вуда
def file_exists(file_path):
return file_path and os.path.isfile(file_path):
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. Я, вероятно, мог бы просто обернуть это в try / except, но я чувствовал, что так это более явно.
return file_path and os.path.isfile(file_path)
Вот однострочная команда Python для среды командной строки Linux. Я нахожу это ОЧЕНЬ УДОБНЫМ, так как я не такой уж горячий парень с Bash.
python -c "import os.path; print os.path.isfile('/path_to/file.xxx')"
Надеюсь, это поможет.
[ -f "${file}" ] && echo "file found" || echo "file not found"
(то же самое, что и if [ ... ]; then ...; else ...; fi
).
Вы можете использовать библиотеку "OS" Python:
>>> import os
>>> os.path.exists("C:\\Users\\####\\Desktop\\test.txt")
True
>>> os.path.exists("C:\\Users\\####\\Desktop\\test.tx")
False
os.path.exists
возвращает истину для вещей, которые не являются файлами, например каталогов. Это дает ложные срабатывания. См. Другие ответы, рекомендующие os.path.isfile
.
exists
в порядке. Если цель состоит в том, чтобы определить, безопасно ли открывать предположительно существующий файл, то критика оправдана и существует недостаточно точно. К сожалению, OP не указывает, какая цель является желаемой (и, вероятно, больше этого не будет).
Как проверить, существует ли файл, без использования оператора try?
В 2016 году это, пожалуй, самый простой способ проверить, существует ли файл и является ли он файлом:
import os
os.path.isfile('./file.txt') # Returns True if exists, else False
isfile
на самом деле является просто вспомогательным методом, который внутри использует os.stat
и stat.S_ISREG(mode)
под ним. Этот os.stat
- метод нижнего уровня, который предоставит вам подробную информацию о файлах, каталогах, сокетах, буферах и многом другом. Подробнее о os.stat здесь
Примечание. Однако этот подход никоим образом не заблокирует файл, и поэтому ваш код может стать уязвимым для « времени проверки до времени использования » ( TOCTTOU ) ошибки.
Таким образом, создание исключений считается приемлемым и питоническим подходом для управления потоком в вашей программе. И следует рассмотреть возможность обработки отсутствующих файлов с помощью IOErrors, а не операторов if
( просто совет ).
import os.path
def isReadableFile(file_path, file_name):
full_path = file_path + "/" + file_name
try:
if not os.path.exists(file_path):
print "File path is invalid."
return False
elif not os.path.isfile(full_path):
print "File does not exist."
return False
elif not os.access(full_path, os.R_OK):
print "File cannot be read."
return False
else:
print "File can be read."
return True
except IOError as ex:
print "I/O error({0}): {1}".format(ex.errno, ex.strerror)
except Error as ex:
print "Error({0}): {1}".format(ex.errno, ex.strerror)
return False
#------------------------------------------------------
path = "/usr/khaled/documents/puzzles"
fileName = "puzzle_1.txt"
isReadableFile(path, fileName)
isReadableFile(path,fileName)
вернет True
, если файл доступен и доступен для чтения процессу \ программе \ потоку
Если причина, по которой вы проверяете, заключается в том, чтобы вы могли сделать что-то вроде 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/1960959
open('file', 'r+')
), а потом искать до конца.
У вас есть функция os.path.exists
:
import os.path
os.path.exists(file_path)
Это возвращает True
как для файлов, так и для каталогов, но вместо этого вы можете использовать
os.path.isfile(file_path)
Чтобы проверить, является ли это конкретным файлом. Он следует символическим ссылкам.
В отличие от isfile()
, exists()
вернет True
для каталогов. Итак, в зависимости от того, нужны ли вам только простые файлы или также каталоги, вы будете использовать isfile()
или exists()
. Вот простой вывод REPL:
>>> os.path.isfile("/etc/password.txt")
True
>>> os.path.isfile("/etc")
False
>>> os.path.isfile("/does/not/exist")
False
>>> os.path.exists("/etc/password.txt")
True
>>> os.path.exists("/etc")
True
>>> os.path.exists("/does/not/exist")
False
import os.path
if os.path.isfile(filepath):
Если файл предназначен для открытия, вы можете использовать один из следующих способов:
with open('somefile', 'xt') as f: #Using the x-flag, Python3.3 and above
f.write('Hello\n')
if not os.path.exists('somefile'):
with open('somefile', 'wt') as f:
f.write("Hello\n")
else:
print('File already exists!')
ОБНОВЛЕНИЕ
Чтобы избежать путаницы и на основании полученных ответов, текущий ответ находит либо файл , либо каталог с заданным именем.
os.path.exists
возвращает истину для вещей, которые не являются файлами, например каталогов. Это дает ложные срабатывания. См. Другие ответы, рекомендующие os.path.isfile
.
if os.path.isfile(path_to_file):
try:
open(path_to_file)
pass
except IOError as e:
print "Unable to open file"
Создание исключений считается приемлемым и питоническим подходом для управления потоком в вашей программе. Рассмотрите возможность обработки отсутствующих файлов с помощью IOErrors. В этой ситуации будет вызвано исключение IOError, если файл существует, но у пользователя нет разрешений на чтение.
SRC: http://www.pfinn.net/python-check-if-file-exists. html
Похожие вопросы
Новые вопросы
python
Python - это многопарадигмальный, динамически типизированный, многоцелевой язык программирования. Он разработан для быстрого изучения, понимания и использования, а также для обеспечения чистого и единообразного синтаксиса. Обратите внимание, что Python 2 официально не поддерживается с 01.01.2020. Тем не менее, для вопросов о Python, связанных с версией, добавьте тег [python-2.7] или [python-3.x]. При использовании варианта Python (например, Jython, PyPy) или библиотеки (например, Pandas и NumPy) включите его в теги.