38 Вопрос: Как проверить, существует ли файл без исключений?

вопрос создан в Mon, Nov 5, 2018 12:00 AM

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

    
5065
  1. Почему вы хотите избежать исключений в Python? Это идиоматический способ делать вещи.
    2019-03-27 14: 39: 30Z
  2. Потому что, если у вас есть важный фрагмент кода, зависящий от несуществующего файла, его включение в предложение except: сделает это исключение, возникающее в этой части вашего кода. вызовет сбивающее с толку сообщение (вторая ошибка возникает при обработке первого.)
    2019-05-24 10: 40: 02Z
30 ответов                              30                         

Если причина, по которой вы проверяете, заключается в том, что вы можете сделать что-то вроде 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
    
4642
2019-05-13 10: 40: 43Z
  1. относительно первого замечания (к сожалению, используйте "try", если проверка перед открытием), к сожалению, это не будет работать, если вы хотите открыть для добавления, будучи уверенным, что оно существует раньше, поскольку 'a' режим будет создан, если не существует.
    2018-06-20 07: 58: 09Z
  2. Обратите внимание, что FileNotFoundError был введен в Python 3. Если вам также необходимо поддерживать Python 2.7, а также Python 3, вы можете использовать вместо него IOError (которые являются подклассами FileNotFoundError) stackoverflow.com/a/21368457/1960959
    2019-03-29 13: 44: 15Z
  3. @ makapuf Вы можете открыть его для "обновления" (open('file', 'r+')) и затем искать до конца.
    2019-04-30 17: 45: 44Z
  4. os.path.isfile (fname) - это все, что мне нужно. Спасибо!
    2019-05-30 10: 30: 46Z

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

import os.path
os.path.exists(file_path)

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

 
os.path.isfile(file_path)

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

    
1936
2018-10-19 08: 58: 59Z

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

 
>>> print os.path.isfile("/etc/password.txt")
True
>>> print os.path.isfile("/etc")
False
>>> print os.path.isfile("/does/not/exist")
False
>>> print os.path.exists("/etc/password.txt")
True
>>> print os.path.exists("/etc")
True
>>> print os.path.exists("/does/not/exist")
False
    
893
2016-12-02 19: 33: 06Z
 
import os.path

if os.path.isfile(filepath):
    
553
2017-06-21 20: 33: 46Z

Используйте os.path.isfile() с os.access() : р>  

import os
import os.path

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"
    
271
2018-07-16 10: 21: 08Z
  1. с несколькими условиями, некоторые из которых излишни, менее ясен и явен.
    2013-04-09 05: 45: 27Z
  2. Это также избыточно. Если файл не существует, os.access() вернет false.
    2018-03-13 00: 01: 19Z
  3. @ EJP В linux файлы могут существовать, но недоступны.
    2018-07-16 21: 30: 18Z
  4. , поскольку у вас import os, вам не нужно снова import os.path, поскольку он уже является частью os. Вам просто нужно импортировать os.path, если вы собираетесь использовать функции из os.path, а не из самого os, чтобы импортировать меньшую вещь, но, поскольку вы используете os.access и os.R_OK, второй импорт не нужен.
    2018-08-24 13: 10: 26Z
 
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
    
254
2018-06-02 20: 52: 01Z

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

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

Постановка проблемы :

  1. Проверить наличие файла ( спорный : также папка ("специальный" файл)?)
  2. Не используйте try / , кроме / else / finally блоки

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

  1. [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 exists(path):
            """Test whether a path exists.  Returns False for broken symbolic links"""
            try:
                st = os.stat(path)
            except os.error:
                return False
            return True
        

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

    1,1. [Python 3]: путь. is_file () р>

    • Это более причудливый (и более python ic) способ обработки путей, но
    • Под капотом он делает точно то же самое ( pathlib.py , строка ~ # 1330 ):

       
      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
      
  2. [Python 3]: с менеджерами контекста оператора . Или:

    • Создать один.

       
      class Swallow:  # Dummy example
          swallowed_exceptions = (FileNotFoundError,)
      
          def __enter__(self):
              print("Entering...")
      
          def __exit__(self, exc_type, exc_value, exc_traceback):
              print("Exiting:", exc_type, exc_value, exc_traceback)
              return exc_type in Swallow.swallowed_exceptions  # only swallow FileNotFoundError (not e.g. TypeError - if the user passes a wrong argument like None or float or ...)
      
      • И его использование - я воспроизведу поведение os.path.isfile (обратите внимание, что это только для демонстрационных целей, не пытайтесь написать такой код для production ):  

        import os
        import stat
        
        
        def isfile_seaman(path):  # Dummy func
            result = False
            with Swallow():
                result = stat.S_ISREG(os.stat(path).st_mode)
            return result
        
    • Используйте [Python 3]: contextlib. suppress ( * exceptions ) , который был специально разработан для выборочного подавления исключений


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

      

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

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


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

  4. [Python 3]: os. доступ ( path, mode, *, dir_fd = None ,ffective_ids = False, follow_symlinks = True ) , поведение которого близко к os.path.exists (на самом деле оно шире, в основном из-за 2 nd аргумент)

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

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

    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 , вот пример:

     
    Python 3.5.3 (v3.5.3:1880cb95a742, Jan 16 2017, 16:02:32) [MSC v.1900 64 bit (AMD64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> 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 (несмотря на Юникод ). > связанные различия между ними)
    • Хотя это относится к очень конкретной области, об этом не упоминалось ни в одном из предыдущих ответов


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

     
    Python 3.5.2 (default, Nov 17 2016, 17:05:23)
    [GCC 5.4.0 20160609] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> 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) : р>

        

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

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

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

    Но, поскольку это больше похоже на обходной путь, я остановлюсь здесь.

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

    • Win

       
      (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
      

Итог :

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

Заключительные примечания :

  • Я постараюсь держать его в курсе, любые предложения приветствуются, я добавлю что-нибудь полезное, что придет в ответ
216
2019-02-08 09: 36: 33Z
  1. Можете ли вы уточнить это утверждение? «Хотя это не очень хорошая практика, я использую os.F_OK в вызове, но это только для ясности (его значение равно 0)»
    2017-11-19 01: 46: 40Z
  2. @ sk8asd123: Трудно сделать это в комментарии: обычно лучше использовать константы с функциями, с которыми они объединяются. Это применимо при работе с несколькими модулями, которые определяют одну и ту же константу, поскольку некоторые из них могут быть устаревшими, и лучше всего синхронизировать функции и константы. Работая с ctypes (вызывая функции напрямую), я должен был определить константу (из MSDN ) или не использовать константу вообще. Это просто руководство, которое я использую, в 99,9% это, вероятно, не имеет никакого значения (функционально).
    2017-11-19 23: 54: 34Z
  3. @ CristiFati: по состоянию на 3.6, glob.iglobglob.glob также) основаны на os.scandir , так что теперь лениво; чтобы получить первое попадание в каталог из 10M файлов, вы сканируете только до первого попадания. И даже до 3.6, если вы используете методы glob без каких-либо подстановочных знаков, функция умная: она знает, что вы можете сделать только один удар, поэтому упрощает глобализацию до os.path.isdir или os.path.lexists (зависит ото том, заканчивается ли путь в /).
    2017-11-29 18: 29: 02Z
  4. Эта вторая часть моего комментария (глобализация без подстановочных знаков на самом деле не выполняет итерации папки и никогда не имеет) означает, что это совершенно эффективное решение проблемы (медленнее чем прямой вызов os.path.isdir или os.path.lexist, так как это набор вызовов функций уровня Python и строковых операций, прежде чем он решит, что эффективный путь жизнеспособен, но никаких дополнительных системных вызовов или операций ввода-вывода, что на несколько порядков медленнее).
    2017-11-29 18: 38: 49Z

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

 
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")
    
146
2018-01-14 04: 07: 53Z
  1. Пока вы намереваетесь получить доступ к файлу, условие гонки существует , независимо от того, как создается ваша программа. Ваша программа не может гарантировать, что другой процесс на компьютере не изменил файл. Эрик Липперт называет это экзогенным исключением . Вы не можете избежать этого, предварительно проверив существование файла.
    2014-11-23 18: 37: 59Z
  2. @ IsaacSupeene Рекомендуется сделать как можно меньше окна операции (файла) с последующей надлежащей обработкой исключений
    2018-07-28 02: 52: 48Z

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
    
133
2017-12-04 14: 45: 12Z

Предпочитайте инструкцию try. Это считается лучшим стилем и избегает условий гонки.

Не верь мне на слово. Есть много поддержки этой теории. Вот пара:

117
2014-04-28 01: 01: 59Z
  1. Пожалуйста, добавьте лучшие источники, чтобы поддержать ваше утверждение.
    2015-09-10 09: 09: 37Z
  2. Приведенная ссылка "Избегание условий гонки" (поддержка Apple Dev) не поддерживает ваш ответ. Это касается только использования временных файлов, которые содержат конфиденциальную информацию в плохо спроектированных операционных системах, которые неправильно ограничивают временные файлы /каталоги песочницей из-за ограниченных разрешений. Используя try...exceptв любом случае не поможет решить эту проблему.
    2015-09-28 15: 38: 00Z
  3. @ chrisz Я не думаю, что он только для ссылок - он фактически содержит информацию, отличную от ссылки.
    2018-02-19 04: 30: 09Z
  4. Проблема этого метода заключается в том, что если у вас есть важный фрагмент кода, зависящий от несуществующего файла, то включение его в предложение except: приведет к возникновению исключения в этой части вашего кода возникнет сбивающее с толку сообщение (вторая ошибка возникает при обработке первого.)
    2019-05-24 10: 43: 34Z
  

Как проверить, существует ли файл с использованием 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 или иным образом проверьте 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 не совсем правильно, потому что каталоги не являются файлами (за исключением того, что в смысле everything является файлом).

 
>>> 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.

Как избежать условий гонки без попытки: 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()
... 
>>> 

Для более ранних Питонов, вы можете бросить свой собственный 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:
    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!), что является хорошим способом скрыть ошибки.

Похоже, это поощряет пользователей применять плохие методы.

    
110
2018-02-25 20: 45: 39Z
 
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.

    
82
2017-05-16 16: 36: 46Z
  1. Этот ответ неверный. os.path.exists возвращает true для вещей, которые не являются файлами, например, для каталогов. Это дает ложные срабатывания. Посмотрите другие ответы, которые рекомендуют os.path.isfile.
    2015-08-01 13: 56: 22Z

Тестирование файлов и папок с os.path.isfile(), os.path.isdir() и os.path.exists()

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

enter описание изображения здесь

Вы также можете проверить, является ли файл файлом определенного типа, используя 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
    
76
2016-10-08 12: 43: 02Z

В 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():
    ...
    
67
2017-05-27 01: 00: 22Z
  1. Могу я спросить: в чем преимущество использования модуля 'pathlib' вместо модуля 'os' в python3 для этой проверки?
    2016-02-25 08: 55: 33Z
  2. pathlib - решение ООП Python для путей. Вы можете сделать намного больше с этим. Если вам просто нужно проверить существование, преимущество не так велико.
    2016-02-25 10: 44: 49Z

Не похоже, что между try /исключением и 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'

Если вам нужна блокировка файла, это другое дело.

    
62
2015-08-25 03: 12: 24Z
  1. Этот ответ неверный. os.path.exists возвращает true для вещей, которые не являются файлами, например, для каталогов. Это дает ложные срабатывания. Посмотрите другие ответы, которые рекомендуют os.path.isfile.
    2015-08-01 13: 54: 35Z
  2. В третьем примере я создаю ссылку с именем filepath с правильным временем, а BAM вы перезаписываете целевой файл. Чтобы избежать этой проблемы, вы должны сделать open(filepath, 'wx') в блоке try...except.
    2015-08-24 14: 05: 09Z
  3. Во втором примере, по крайней мере, в Windows, вы получите OSError, если filepath + '.old' уже существует: «В Windows, если dst уже существует, OSError будет вызываться, даже если это файл; может быть невозможно реализовать атомарное переименование, когда dst присваивает имя существующему файлу. "
    2016-05-24 14: 14: 04Z
  4. @ TomMyddeltyn: Начиная с Python 3.3, os.replace переносимо выполняет автоматическую замену файла назначения (он идентичен поведению Linux в os.rename) (он только выдает ошибки, если имя назначения существует и является каталогом). Итак, вы застряли на 2.x, но у пользователей Py3 был хороший выбор уже несколько лет.
    2017-11-29 18: 14: 56Z
  5. В примере rename: это все равно должно быть сделано с try/except. os.rename (или os.replace на современном Python) является атомарным; проверка его, а затем переименование приводит к ненужной гонке и дополнительным системным вызовам. Просто сделай try: os.replace(filepath, filepath + '.old') except OSError: pass
    2017-11-29 18: 17: 31Z

Вы можете попробовать это (безопаснее):

 
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] Нет такого файла или каталога:   'Whatever.txt') р>

Затем, в зависимости от результата, ваша программа может просто продолжать работать оттуда, или вы можете написать код, чтобы остановить его, если хотите.

    
53
2017-05-27 00: 43: 51Z
  1. В исходном вопросе запрашивалось решение, которое не использует try
    2014-04-23 13: 10: 01Z
  2. Этот ответ не попадает в точку OP. Проверка это файл существует не СэмЭто как проверка, можете ли вы открыть его. В некоторых случаях файл существует, но по разным причинам его нельзя открыть.
    2016-02-17 18: 52: 12Z

Хотя я всегда рекомендую использовать операторы try и except, для вас есть несколько возможностей (мой личный фаворит - использование os.access):

  1. Попробуйте открыть файл:

    Открытие файла всегда проверяет его наличие. Вы можете сделать функцию просто так:

     
    def File_Existence(filepath):
        f = open(filepath)
        return True
    

    Если это False, он остановит выполнение с неуправляемым IOError или OSError в более поздних версиях Python. Чтобы поймать исключение, Вы должны использовать попытку, кроме пункта. Конечно, вы всегда можете используйте оператор try кроме `(например, hsandt за то, что заставил меня задуматься):

     
    def File_Existence(filepath):
        try:
            f = open(filepath)
        except IOError, OSError: # Note OSError is for later versions of Python
            return False
    
        return True
    
  2. Используйте 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
    
  3. Используйте os.access(path, mode):

    Это проверит, есть ли у вас доступ к файлу. Он проверит разрешения. На основе документации os.py, набрав os.F_OK, он проверит наличие пути. Однако использование этого создаст дыру в безопасности, так как кто-то может атаковать ваш файл, используя время между проверкой разрешений и открытием файла. Вместо этого вам следует перейти непосредственно к открытию файла вместо проверки его прав доступа. ( EAFP vs 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), чтобы вы могли надеяться определить вашу проблему. Я надеюсь, что это помогает! :)

    
48
2017-05-27 00: 52: 18Z

Дата: 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']}
    
42
2018-12-23 10: 46: 13Z

Кроме того, os.access():

 
if os.access("myfile", os.R_OK):
    with open("myfile") as fp:
        return fp.read()

Будучи R_OK, W_OK и X_OK флагами для проверки прав доступа ( док ). р>     

33
2016-05-04 15: 24: 02Z

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

 
>>> 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!')

UPDATE

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

    
30
2018-07-22 19: 12: 53Z
  1. Этот ответ неверный. os.path.exists возвращает true для вещей, которые не являются файлами, например, для каталогов. Это дает ложные срабатывания. Посмотрите другие ответы, которые рекомендуют os.path.isfile.
    2015-08-01 13: 55: 01Z
  2. также получил проблему ложного срабатывания.
    2018-05-19 21: 33: 55Z
  3. docs.python.org/3/library/os.path.html#os.path.exists К приведенному выше заявлению от chris > os.path.exists (путь) > Верните True, если путь ссылается на существующий путь или дескриптор открытого файла. Возвращает False для неработающих символических ссылок. На некоторых платформах эта функция может возвращать False, если не предоставлено разрешение на выполнение os.stat () для запрошенного файла, даже если путь физически существует. Изменено в версии 3.3: путь теперь может быть целым числом: True возвращается, если это дескриптор открытого файла, False в противном случае. Изменено в версии 3.6: Принимает объект, похожий на путь.
    2018-08-31 23: 24: 22Z
 
if os.path.isfile(path_to_file):
    try: 
        open(path_to_file)
            pass
    except IOError as e:
        print "Unable to open file"
  

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

SRC: http://www.pfinn.net/python-check-if-file -exists.html р>     

20
2015-07-18 17: 41: 08Z
  1. ОП спросил, как проверить, существует ли файл. Файл может существовать, но вы не можете его открыть. Поэтому использование открытия файла в качестве прокси-сервера для проверки того, существует ли файл, является неправильным: будет иметь ложные отрицания.
    2016-02-17 18: 58: 54Z

Если вы уже импортировали NumPy для других целей, то нет необходимости импортировать другие библиотеки, такие как pathlib, os, paths и т. д.

 
import numpy as np
np.DataSource().exists("path/to/your/file")

Это вернет true или false в зависимости от его существования.

    
18
2018-09-01 01: 00: 51Z

Вы можете написать предложение Брайана без 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
    
17
2017-05-27 00: 48: 31Z

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

Вы можете следовать этим трем путям:

  

Примечание 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()
    
16
2018-03-04 06: 24: 37Z

Добавление еще одного небольшого изменения, которое не совсем отражено в других ответах.

Это будет обрабатывать случай, когда 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):
    
15
2017-04-07 16: 10: 59Z
  1. if (x) return true; else return false; - это всего лишь return x. Ваши последние четыре строки могут стать return os.path.isfile(file_path). Пока мы работаем над этим, всю функцию можно упростить до return file_path and os.path.isfile(file_path).
    2017-01-04 22: 50: 16Z
  2. Вы должны быть осторожны с return x в случае if (x). Python будет рассматривать пустую строку False, в этом случае мы будем возвращать пустую строку вместо bool. Цель этой функции - всегда возвращать bool.
    2017-01-05 17: 08: 43Z
  3. Истина. В этом случае, однако, x - это os.path.isfile(..), так что это уже бул.
    2017-01-05 17: 10: 24Z
  4. os.path.isfile(None) вызывает исключение, поэтому я добавил проверку if. Возможно, я мог бы просто обернуть его в попытку /за исключением, но я чувствовал, что это было более явным образом.
    2017-01-05 17: 13: 10Z
  5. return file_path and os.path.isfile(file_path)
    2017-04-06 10: 35: 01Z

Я являюсь автором пакета, который существует уже около 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/pox/blob/89f90fb308f285ca7a62eabe2c38acb87e89dad9 /pox/shutils.py#L190 р>     

15
2017-05-27 00: 59: 52Z

Вот однострочная команда Python для среды командной строки Linux. Я нахожу это ОЧЕНЬ ХЕНДИ, так как я не такой крутой парень из Баша.

 
python -c "import os.path; print os.path.isfile('/path_to/file.xxx')"

Надеюсь, это полезно.

    
14
2015-08-29 16: 15: 29Z
  1. Однострочная проверка в bash: [ -f "${file}" ] && echo "file found" || echo "file not found" (что совпадает с if [ ... ]; then ...; else ...; fi).
    2015-10-01 07: 48: 29Z

Вы можете использовать библиотеку "OS" Python:

 
>>> import os
>>> os.path.exists("C:\\Users\\####\\Desktop\\test.txt") 
True
>>> os.path.exists("C:\\Users\\####\\Desktop\\test.tx")
False
    
11
2017-05-27 00: 49: 25Z
  1. Этот ответ неверный. os.path.exists возвращает true для вещей, которые не являются файлами, например, для каталогов. Это дает ложные срабатывания. Посмотрите другие ответы, которые рекомендуют os.path.isfile.
    2015-08-01 13: 55: 13Z
  2. @ Крис Джонсон, функция os.path.exists () проверяет, существует ли путь в системе. ПУТЬ может быть КАТАЛОГОМ или ФАЙЛОМ. Это будет хорошо работать в обоих случаях. Пожалуйста, попробуйте с некоторыми примерами
    2015-08-02 14: 51: 41Z
  3. Итак, этот ответ работает. Отлично. Если путь, это не путь к файлу. Это был вопрос? Нет.
    2016-04-14 23: 33: 56Z
  4. Это зависит. Если целью определения существования «файла» является выяснениеесли путь уже существует (и, следовательно, не является путем, в котором новые данные могут быть сохранены без удаления другой информации), тогда exists подойдет. Если цель состоит в том, чтобы определить, безопасно ли открывать предположительно существующий файл, то критика оправдана и существует недостаточно точно. К сожалению, OP не указывает, какая цель является желаемой (и, вероятно, больше не будет делать этого).
    2017-09-05 11: 24: 42Z
  

Как проверить, существует ли файл, без использования оператора 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 ).

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

    
11
2017-05-27 00: 57: 43Z
 
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)
    
9
2015-10-08 21: 22: 53Z
  1. это True и False, верно ..?
    2015-08-08 21: 27: 18Z
  2. @ j6m8 да, isReadableFile(path,fileName) вернет True, если файл доступен и читается процессом \program \thread
    2015-08-09 07: 46: 31Z
источник размещен Вот