Меню

Ошибка отсутствия файла python

Кратко: вместо if exists(): open() используйте просто open().


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

#!/usr/bin/env python
# -*- coding: utf-8 -*-
try:
    file = open('input.txt')
except IOError as e:
    print(u'не удалось открыть файл')
else:
    with file:
        print(u'делаем что-то с файлом')

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

В Питоне часто предпочтителен «Проще просить прощения, чем разрешения» ( «It is Easier to Ask for Forgiveness than Permission» — EAFP) подход вместо «Look before you leap.» более распространённого в С.


Ответы на комментарии:

  1. Где блок finally в котором вы закрывается поток

finally здесь не нужен. Если код попал в except блок, то файл не открыт — нечего закрывать. В else ветке, где файл открыт, with file: конструкция всегда закрывает файл при выходе из блока (нормальном или когда исключение возникло).

  1. Конструкция try-exept-else многими считается плохо читаемой.

Обычно try/except не используется на том же уровне, то есть в коде используется просто:

with open('input.txt') as file:
    print(u'делаем что-то с файлом')

а возможные исключения выше по стеку обрабатываются. Но если вы хотите обработать ошибку в open() на том же уровне, то вы обязаны использовать try/except (open() сигнализирует ошибки с помощью исключений).

  1. Каждый раз, когда файла нет, вы вызываете прерывание ОС (на нем строится механизм обработки исключения) самостоятельно, не слишком ли это раcточительно?

Исключения выбрасываются в случае ошибки в Питоне хотите вы этого или нет. Вот реализация os.path.exists() из стандартной библиотеки:

def exists(path):
    try:
        os.stat(path)
    except OSError:
        return False
    return True

фактически, используя open() напрямую, а не if exists(): open() мы уменьшаем количество системных вызовов.

  1. Ваш код занял 7 строчек, не лучше ли эту задачу поручить операционной системе командой os.path.exists(path_to_file) в пару строчек ?

Длина кода, который не работает, не имеет значения. Ещё раз: вызов os.path.exists() не гарантирует что файл существует когда вы попытаетесь вызвать open() позднее: всё равно придётся обрабатывать ошибки.

Стоит упомянуть, что если отсутствие файла не является ошибкой в вашем случае (ожидается программой), то вполне можно os.path.exists() или его аналоги использовать, чтобы подчеркнуть вероятность отсутствия файла для читателя кода (но так как последующее открытие файла может быть всё равно неудачным, то это не освобождает код от добавления обработки ошибок, подходящего для вашей задачи, такого как try/except выше).

How do I check whether a file exists, using Python, without using a try statement?

Now available since Python 3.4, import and instantiate a Path object with the file name, and check the is_file method (note that this returns True for symlinks pointing to regular files as well):

>>> from pathlib import Path
>>> Path('/').is_file()
False
>>> Path('/initrd.img').is_file()
True
>>> Path('/doesnotexist').is_file()
False

If you’re on Python 2, you can backport the pathlib module from pypi, pathlib2, or otherwise check isfile from the os.path module:

>>> import os
>>> os.path.isfile('/')
False
>>> os.path.isfile('/initrd.img')
True
>>> os.path.isfile('/doesnotexist')
False

Now the above is probably the best pragmatic direct answer here, but there’s the possibility of a race condition (depending on what you’re trying to accomplish), and the fact that the underlying implementation uses a try, but Python uses try everywhere in its implementation.

Because Python uses try everywhere, there’s really no reason to avoid an implementation that uses it.

But the rest of this answer attempts to consider these caveats.

Longer, much more pedantic answer

Available since Python 3.4, use the new Path object in pathlib. Note that .exists is not quite right, because directories are not files (except in the unix sense that everything is a file).

>>> from pathlib import Path
>>> root = Path('/')
>>> root.exists()
True

So we need to use is_file:

>>> root.is_file()
False

Here’s the help on is_file:

is_file(self)
    Whether this path is a regular file (also True for symlinks pointing
    to regular files).

So let’s get a file that we know is a file:

>>> import tempfile
>>> file = tempfile.NamedTemporaryFile()
>>> filepathobj = Path(file.name)
>>> filepathobj.is_file()
True
>>> filepathobj.exists()
True

By default, NamedTemporaryFile deletes the file when closed (and will automatically close when no more references exist to it).

>>> del file
>>> filepathobj.exists()
False
>>> filepathobj.is_file()
False

If you dig into the implementation, though, you’ll see that is_file uses 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

Race Conditions: Why we like try

We like try because it avoids race conditions. With try, you simply attempt to read your file, expecting it to be there, and if not, you catch the exception and perform whatever fallback behavior makes sense.

If you want to check that a file exists before you attempt to read it, and you might be deleting it and then you might be using multiple threads or processes, or another program knows about that file and could delete it — you risk the chance of a race condition if you check it exists, because you are then racing to open it before its condition (its existence) changes.

Race conditions are very hard to debug because there’s a very small window in which they can cause your program to fail.

But if this is your motivation, you can get the value of a try statement by using the suppress context manager.

Avoiding race conditions without a try statement: suppress

Python 3.4 gives us the suppress context manager (previously the ignore context manager), which does semantically exactly the same thing in fewer lines, while also (at least superficially) meeting the original ask to avoid a try statement:

from contextlib import suppress
from pathlib import Path

Usage:

>>> with suppress(OSError), Path('doesnotexist').open() as f:
...     for line in f:
...         print(line)
... 
>>>
>>> with suppress(OSError):
...     Path('doesnotexist').unlink()
... 
>>> 

For earlier Pythons, you could roll your own suppress, but without a try will be more verbose than with. I do believe this actually is the only answer that doesn’t use try at any level in the Python that can be applied to prior to Python 3.4 because it uses a context manager instead:

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)

Perhaps easier with a try:

from contextlib import contextmanager

@contextmanager
def suppress(*exceptions):
    try:
        yield
    except exceptions:
        pass

Other options that don’t meet the ask for «without try»:

isfile

import os
os.path.isfile(path)

from the docs:

os.path.isfile(path)

Return True if path is an existing regular file. This follows symbolic
links, so both islink() and isfile() can be true for the same path.

But if you examine the source of this function, you’ll see it actually does use a try statement:

# 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

All it’s doing is using the given path to see if it can get stats on it, catching OSError and then checking if it’s a file if it didn’t raise the exception.

If you intend to do something with the file, I would suggest directly attempting it with a try-except to avoid a race condition:

try:
    with open(path) as f:
        f.read()
except OSError:
    pass

os.access

Available for Unix and Windows is os.access, but to use you must pass flags, and it does not differentiate between files and directories. This is more used to test if the real invoking user has access in an elevated privilege environment:

import os
os.access(path, os.F_OK)

It also suffers from the same race condition problems as isfile. From the docs:

Note:
Using access() to check if a user is authorized to e.g. open a file
before actually doing so using open() creates a security hole, because
the user might exploit the short time interval between checking and
opening the file to manipulate it. It’s preferable to use EAFP
techniques. For example:

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

is better written as:

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()

Avoid using os.access. It is a low level function that has more opportunities for user error than the higher level objects and functions discussed above.

Criticism of another answer:

Another answer says this about os.access:

Personally, I prefer this one because under the hood, it calls native APIs (via «${PYTHON_SRC_DIR}/Modules/posixmodule.c»), but it also opens a gate for possible user errors, and it’s not as Pythonic as other variants:

This answer says it prefers a non-Pythonic, error-prone method, with no justification. It seems to encourage users to use low-level APIs without understanding them.

It also creates a context manager which, by unconditionally returning True, allows all Exceptions (including KeyboardInterrupt and SystemExit!) to pass silently, which is a good way to hide bugs.

This seems to encourage users to adopt poor practices.

How do I check whether a file exists, using Python, without using a try statement?

Now available since Python 3.4, import and instantiate a Path object with the file name, and check the is_file method (note that this returns True for symlinks pointing to regular files as well):

>>> from pathlib import Path
>>> Path('/').is_file()
False
>>> Path('/initrd.img').is_file()
True
>>> Path('/doesnotexist').is_file()
False

If you’re on Python 2, you can backport the pathlib module from pypi, pathlib2, or otherwise check isfile from the os.path module:

>>> import os
>>> os.path.isfile('/')
False
>>> os.path.isfile('/initrd.img')
True
>>> os.path.isfile('/doesnotexist')
False

Now the above is probably the best pragmatic direct answer here, but there’s the possibility of a race condition (depending on what you’re trying to accomplish), and the fact that the underlying implementation uses a try, but Python uses try everywhere in its implementation.

Because Python uses try everywhere, there’s really no reason to avoid an implementation that uses it.

But the rest of this answer attempts to consider these caveats.

Longer, much more pedantic answer

Available since Python 3.4, use the new Path object in pathlib. Note that .exists is not quite right, because directories are not files (except in the unix sense that everything is a file).

>>> from pathlib import Path
>>> root = Path('/')
>>> root.exists()
True

So we need to use is_file:

>>> root.is_file()
False

Here’s the help on is_file:

is_file(self)
    Whether this path is a regular file (also True for symlinks pointing
    to regular files).

So let’s get a file that we know is a file:

>>> import tempfile
>>> file = tempfile.NamedTemporaryFile()
>>> filepathobj = Path(file.name)
>>> filepathobj.is_file()
True
>>> filepathobj.exists()
True

By default, NamedTemporaryFile deletes the file when closed (and will automatically close when no more references exist to it).

>>> del file
>>> filepathobj.exists()
False
>>> filepathobj.is_file()
False

If you dig into the implementation, though, you’ll see that is_file uses 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

Race Conditions: Why we like try

We like try because it avoids race conditions. With try, you simply attempt to read your file, expecting it to be there, and if not, you catch the exception and perform whatever fallback behavior makes sense.

If you want to check that a file exists before you attempt to read it, and you might be deleting it and then you might be using multiple threads or processes, or another program knows about that file and could delete it — you risk the chance of a race condition if you check it exists, because you are then racing to open it before its condition (its existence) changes.

Race conditions are very hard to debug because there’s a very small window in which they can cause your program to fail.

But if this is your motivation, you can get the value of a try statement by using the suppress context manager.

Avoiding race conditions without a try statement: suppress

Python 3.4 gives us the suppress context manager (previously the ignore context manager), which does semantically exactly the same thing in fewer lines, while also (at least superficially) meeting the original ask to avoid a try statement:

from contextlib import suppress
from pathlib import Path

Usage:

>>> with suppress(OSError), Path('doesnotexist').open() as f:
...     for line in f:
...         print(line)
... 
>>>
>>> with suppress(OSError):
...     Path('doesnotexist').unlink()
... 
>>> 

For earlier Pythons, you could roll your own suppress, but without a try will be more verbose than with. I do believe this actually is the only answer that doesn’t use try at any level in the Python that can be applied to prior to Python 3.4 because it uses a context manager instead:

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)

Perhaps easier with a try:

from contextlib import contextmanager

@contextmanager
def suppress(*exceptions):
    try:
        yield
    except exceptions:
        pass

Other options that don’t meet the ask for «without try»:

isfile

import os
os.path.isfile(path)

from the docs:

os.path.isfile(path)

Return True if path is an existing regular file. This follows symbolic
links, so both islink() and isfile() can be true for the same path.

But if you examine the source of this function, you’ll see it actually does use a try statement:

# 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

All it’s doing is using the given path to see if it can get stats on it, catching OSError and then checking if it’s a file if it didn’t raise the exception.

If you intend to do something with the file, I would suggest directly attempting it with a try-except to avoid a race condition:

try:
    with open(path) as f:
        f.read()
except OSError:
    pass

os.access

Available for Unix and Windows is os.access, but to use you must pass flags, and it does not differentiate between files and directories. This is more used to test if the real invoking user has access in an elevated privilege environment:

import os
os.access(path, os.F_OK)

It also suffers from the same race condition problems as isfile. From the docs:

Note:
Using access() to check if a user is authorized to e.g. open a file
before actually doing so using open() creates a security hole, because
the user might exploit the short time interval between checking and
opening the file to manipulate it. It’s preferable to use EAFP
techniques. For example:

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

is better written as:

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()

Avoid using os.access. It is a low level function that has more opportunities for user error than the higher level objects and functions discussed above.

Criticism of another answer:

Another answer says this about os.access:

Personally, I prefer this one because under the hood, it calls native APIs (via «${PYTHON_SRC_DIR}/Modules/posixmodule.c»), but it also opens a gate for possible user errors, and it’s not as Pythonic as other variants:

This answer says it prefers a non-Pythonic, error-prone method, with no justification. It seems to encourage users to use low-level APIs without understanding them.

It also creates a context manager which, by unconditionally returning True, allows all Exceptions (including KeyboardInterrupt and SystemExit!) to pass silently, which is a good way to hide bugs.

This seems to encourage users to adopt poor practices.

Разрабатывая приложения вам придется работать с файлами, анализировать большие объемы данных, сохранять пользовательские данные, чтобы они не терялись по завершению работы программы. Также при работе с файлами важно научиться обрабатывать ошибки, чтобы они не привели к аварийному завершению программы. Для этого в Python существуют специальные объекты — исключения, которые создаются для управления ошибок.

Содержание страницы:
1. Чтение файла 
    1.2. Чтение больших файлов и работа с ними
    1.3. Анализ текста из файла
2. Запись в файл
    2.1. Запись в пустой файл
    2.2. Многострочная запись в файл
    2.3. Присоединение данных к файлу
3. Исключения
    3.1. Блоки try-except
    3.2. Блоки try-except-else
    3.3. Блоки try-except с текстовыми файлами
    3.4. Ошибки без уведомления пользователя

1. Чтение файла в Python

В файлах может содержаться любой объем данных, начиная от небольшого рассказа и до сохранения истории погоды за столетия. Чтение файлов особенно актуально для приложений, предназначенных для анализа данных. Приведем пример простой программы, которая открывает файл и выводит его содержимое на экран. В примере я буду использовать файл с числом «Пи» с точностью до 10 знаков после запятой. Скачать этот файл можно прямо здесь ( pi_10.txt ) или самим создать текстовый файл и сохранить под любым именем. Пример программы, которая открывает файл и выводит содержимое на экран:

with open(‘pi_10.txt’) as file_pi:
    digits = file_pi.read()
print(digits)

Код начинается с ключевого слова with. При использование ключевого слова with используемый файл открывается с помощью функции open(), а закрывается автоматически после завершения блока with и вам не придется в конце вызывать функцию close(). Файлы можно открывать и закрывать явными вызовами open() и close(). Функция open() получает один аргумент — имя открываемого файла, в нашем случае ‘pi_10.txt’. Python ищет указанный файл в каталоге, где хранится файл текущей программы. Функция open() возвращает объект, представляющий файл ‘pi_10.txt’. Python сохраняет этот объект в переменной file_pi .  

После появления объекта, представляющего файл ‘pi_10.txt’, используется метод read(), который читает все содержимое файла и сохраняет его в одной строке в переменной contents. В конце с помощью функции print содержимое выводится на экран. Запустив этот файл, мы получим данные, находящиеся в нашем файле ‘pi_10.txt’.

3.1415926535

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

  •  Относительный путь. 

Относительный путь приказывает Python искать файлы в каталоге, который задается относительно каталога, в котором находится текущий файл программы

with open(‘files/имя_файла.txt’) as file:

  • Абсолютный путь. 

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

file_path = ‘/Users/Desktop/files/имя_файла.txt’
with open(file_path) as file:

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

1.2. Чтение больших файлов на Python и работа с ними

В первом примере был файл с 10 знаками после запятой. Теперь давайте проанализируем файл с миллионом знаков числа «Пи» после запятой. Скачать число «Пи» с миллионом знаков после запятой можно отсюда( ‘pi_1000000.txt’ ). Изменять код из первого примера не придется, просто заменим файл, который должен читать Python. 

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

3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679

1000002

Из выходных данных видно, что строка содержит значение «Пи» с точностью до 1 000 000 знаков после запятой. В Python нет никаких ограничений на длину данных, с которыми можно работать, единственное ограничение это объем памяти вашей системы. 

После сохранения данных в переменной можно делать с ними все что угодно. Давайте проверим, входит ли в число «Пи» дата вашего дня рождения. Напишем небольшую программу, которая будет читать файл и проверять входит ли дата день рождения в первый миллион числа «Пи»:

with open(‘pi_1000000.txt‘) as file_pi:
    digits = file_pi.read()
birthday = input(«Введите дату дня рождения: «)
if birthday  in digits:
    print(«Ваш день рождение входит в число ‘Пи'»)
else:
    print(«Ваш день рождение не входит в число ‘Пи'»)

Начало программы не изменилось, читаем файл и сохраняем данные в переменной digits. Далее запрашиваем данные от пользователя с помощью функции input и сохраняем в переменную birstday. Затем проверяем вхождение birstday в digits с помощью команды if-else. Запустив несколько раз программу, получим результат:

Введите дату дня рождения: 260786
Ваш день рождение не входит в число ‘Пи’

Введите дату дня рождения: 260884
Ваш день рождение входит в число ‘Пи’

В зависимости от введенных данных мы получили результат вхождения или не вхождения дня рождения в число «Пи»

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

1.3. Анализ текста из файла на Python

Python может анализировать текстовые файлы, содержащие целые книги. Возьмем книгу «Алиса в стране чудес» и попробуем подсчитать количество слов в книге. Текстовый файл с книгой можете скачать здесь(‘ alice ‘) или загрузить любое другое произведение. Напишем простую программу, которая подсчитает количество слов в книге и сколько раз повторяется имя Алиса в книге.

filename = ‘alice.txt’

with open(filename, encoding=’utf-8′) as file:
    contents = file.read()
n_alice = contents.lower().count(‘алиса’)
words = contents.split()
n_words = len(words)

print(f»Книга ‘Алиса в стране чудес’ содержит {n_words} слов.»)
print(f»Имя Алиса повторяется {n_alice} раз.»)

При открытии файла добавился аргумент encoding=’utf-8′. Он необходим, когда кодировка вашей системы не совпадает с кодировкой читаемого файла. После чтения файла, сохраним его в переменной contents.

Для подсчета вхождения слова или выражений в строке можно воспользоваться методом count(), но прежде привести все слова к нижнему регистру функцией lower(). Количество вхождений сохраним в переменной n_alice

Чтобы подсчитать количество слов в тексе, воспользуемся методом split(), предназначенный для построения списка слов на основе строки. Метод split() разделяет строку на части, где обнаружит пробел и сохраняет все части строки в элементах списка. Пример метода split():

title = ‘Алиса в стране чудес’
print(title.split())

[‘Алиса’, ‘в’, ‘стране’, ‘чудес’]

После использования метода split(), сохраним список в переменной words и далее подсчитаем количество слов в списке, с помощью функции len(). После подсчета всех данных, выведем на экран результат:

Книга ‘Алиса в стране чудес’ содержит 28389 слов.
Имя Алиса повторяется 419 раз.

2.1. Запись в пустой файл в Python

Самый простой способ сохранения данных, это записать их в файл. Чтобы записать текс в файл, требуется вызвать open() со вторым аргументом, который сообщит Python что требуется записать файл. Пример программы записи простого сообщения в файл на Python:

filename = ‘memory.txt’

with open(filename, ‘w’) as file:
    file.write(«Язык программирования Python»)

Для начала определим название и тип будущего файла и сохраним в переменную filename. Затем при вызове функции open() передадим два аргумента. Первый аргумент содержит имя открываемого файла. Второй аргумент ‘ w ‘ сообщает Python, что файл должен быть открыт в режиме записи. Во второй строчке метод write() используется для записи строки в файл. Открыв файл ‘ memory.txt ‘ вы увидите в нем строку:

Язык программирования Python

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

Важно: Открывая файл в режиме записи ‘ w ‘, если файл уже существует, то Python уничтожит его данные перед возвращением объекта файла.

Файлы можно открывать в режимах:

  • чтение ‘ r ‘
  • запись ‘ w ‘
  • присоединение ‘ a ‘
  • режим как чтения, так и записи ‘ r+ ‘

2.2. Многострочная запись в файл на Python

При использовании функции write() символы новой строки не добавляются в записываемый файл:

filename = ‘memory.txt’

with open(filename, ‘w’) as file:
    file.write(«Язык программирования Python»)
    file.write(«Язык программирования Java»)
    file.write(«Язык программирования Perl»)

В результате открыв файл мы увидим что все строки склеились:

Язык программирования PythonЯзык программирования JavaЯзык программирования Perl

Для написания каждого сообщения с новой строки используйте символ новой строки n

filename = ‘memory.txt’

with open(filename, ‘w’) as file:
    file.write(«Язык программирования Pythonn«)
    file.write(«Язык программирования Javan«)
    file.write(«Язык программирования Perln«)

Результат будет выглядеть так:

Язык программирования Python
Язык программирования Java
Язык программирования Perl

2.3. Присоединение данных к файлу на Python 

Для добавления новых данных в файл, вместо того чтобы постоянно перезаписывать файл, откройте файл в режиме присоединения ‘ a ‘. Все новые строки добавятся в конец файла. Возьмем созданный файл из раздела 2.2 ‘memory.txt’. Добавим в него еще пару строк.

filename = ‘memory.txt’

with open(filename, ‘a’) as file:
    file.write(«Hello worldn»)
    file.write(«Полет на лунуn»)

В результате к нашему файлу добавятся две строки:

Язык программирования Python
Язык программирования Java
Язык программирования Perl
Hello world
Полет на луну

3. Исключения в Python

При выполнении программ могут возникать ошибки, для управления ими Python использует специальные объекты, называемые исключениями. Когда в программу включен код обработки исключения, ваша программа продолжится, а если нет, то программа остановится и выведет трассировку с отчетом об исключении. Исключения обрабатываются в блоках try-except. С блоками try-except программы будут работать даже в том случае, если что-то пошло не так.

3.1. Блоки try-except на Python

Приведем пример простой ошибки деления на ноль:

print(7/0)

Traceback (most recent call last):
  File «example.py», line 1, in <module>
    print(7/0)
ZeroDivisionError: division by zero

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

try:
    print(7/0)
except ZeroDivisionError:
    print(«Деление на ноль запрещено»)

Команда print(7/0) помещена в блок try. Если код в блоке try выполняется успешно, то Python пропускает блок except.  Если же код в блоке try создал ошибку, то Python ищет блок except и запускает код в этом блоке. В нашем случае в блоке except выводится сообщение «Деление на ноль запрещено». При выполнение этого кода пользователь увидит понятное сообщение:

Деление на ноль запрещено

Если за кодом try-except следует другой код, то Python продолжит выполнение программы. 

3.2. Блок try-except-else на Python

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

while True:
    first_number = input(«Введите первое число: «)
    if first_number == ‘q’:
        break
    second_number = input(«Введите второе число: «)
    if second_number == ‘q’:
        break
    try:
        a = int(first_number) / int(second_number)
    except ZeroDivisionError:
        print(«Деление на ноль запрещено»)
    else:
        print(f»Частное двух чисел равно {a}»)

Программа запрашивает у пользователя первое число (first_number), затем второе (second_number). Если пользователь не ввел » q « для завершения работы программа продолжается. В блок try помещаем код, в котором возможно появление ошибки. В случае отсутствия ошибки деления, выполняется код else и Python выводит результат на экран. В случае ошибки ZeroDivisionError выполняется блок except и выводится сообщение о запрете деления на ноль, а программа продолжит свое выполнение. Запустив код получим такие результаты:

Введите первое число: 30
Введите второе число: 5
Частное двух чисел равно 6.0
Введите первое число: 7
Введите второе число: 0
Деление на ноль запрещено
Введите первое число:  q

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

3.3. Блок  try-except с текстовыми файлами на Python

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

filename = ‘alice_2.txt’

with open(filename, encoding=’utf-8′) as file:
    contents = file.read()

Так как такого файла не существует, Python выдает исключение:

Traceback (most recent call last):
  File «example.py», line 3, in <module>
    with open(filename, encoding=’utf-8′) as file:
FileNotFoundError: [Errno 2] No such file or directory: ‘alice_2.txt’

FileNotFoundError — это ошибка отсутствия запрашиваемого файла. С помощью блока try-except обработаем ее:

filename = ‘alice_2.txt’

try:
    with open(filename, encoding=’utf-8′) as file:
        contents = file.read()
except FileNotFoundError:
    print(f»Запрашиваемый файл {filename } не найден»)

В результате при отсутствии файла мы получим:

Запрашиваемый файл alice_2.txt не найден

3.4. Ошибки без уведомления пользователя

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

ilename = ‘alice_2.txt’

try:
    with open(filename, encoding=’utf-8′) as file:
        contents = file.read()
except FileNotFoundError:
    pass

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

Далее: Функции json. Сохранение данных Python

Назад: Классы в Python

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

Способность проверять, существует ли файл на диске или нет — очень важно для большинства программ Python:

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

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

В данном руководстве вы увидите три отдельные техники для проверки существования файла в Python, с примерами кода и характерными преимуещствами и недостатками.

Приступим!

Самый простой способ проверки существования файла в Python — это использование методов exists() и isfile() из модуля os.path в стандартной библиотеке.

Эти функции доступны в Python 2 и Python 3.7, и обычно их рекомендуют в первую очередь, если обращаться за помощью к документации Python или гуглу за решением проблемы.

Есть вопросы по Python?

На нашем форуме вы можете задать любой вопрос и получить ответ от всего нашего сообщества!

Telegram Чат & Канал

Вступите в наш дружный чат по Python и начните общение с единомышленниками! Станьте частью большого сообщества!

Паблик VK

Одно из самых больших сообществ по Python в социальной сети ВК. Видео уроки и книги для вас!

Вот пример того, как работать с функцией os.path.exists(). Мы проверим несколько путей (файлы и папки) на наличие:

import os.path

check_file = os.path.exists(‘storage/music.mp3’) # True

print(os.path.exists(‘нет-такого-файла.txt’)) # False

# Проверяем если папка существует.

os.path.exists(‘storage’) # True

Как мы видим, вызов os.path.exists() возвращает True для файлов и папок. Если вы хотите убедиться, что заданный путь указывает на файл, но не на папку, вы можете использовать функцию os.path.isfile()

import os.path

os.path.isfile(‘storage/music.mp3’) # True

os.path.isfile(‘нет-такого-файла.txt’) # False

os.path.isfile(‘storage’) # False, папка существует но это не файл.

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

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

Проверка существует ли файл используя open() и try … except

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

Есть еще один прямолинейный алгоритм Python для проверки существования файла: Вы просто пытаетесь открыть файл при помощи встроенной функции open(), вот так:

open(‘нет-такого-файла.txt’)

    FileNotFoundError:

«[Errno 2] No such file or directory: ‘нет-такого-файла.txt'»

Если файл существует, то файл успешно откроется и вернет валидный объект для дальнейшей обработки файла. Если файл не существует, появится ошибка FileNotFoundError:

Ошибка FileNotFoundError возникает, когда файл или папка запрошена, но не существует. Относится к errno ENOENT.

Это значит, что вы можете получить ошибку FileNotFoundError в своем коде, и использовать ее для обнаружения того, существует файл или нет. Вот пример кода, который демонстрирует работу этой техники:

try:

    f = open(‘нет-такого-файла.txt’)

    f.close()

except FileNotFoundError:

    print(‘Файл не существует!’)

Обратите внимание, мы мгновенно вызываем метод close() для объекта файла для освобождения дескриптора файла. Это считается хорошей практикой при работе с файлами в Python:

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

Вместо того, чтобы закрывать файл при помощи метода close(), есть еще один способ, которым можно воспользоваться контекстным менеджером и оператора with для автоматического закрытия файла.

Теперь, та же техника “просто попробуем открыть файл” также работает для выяснения, является ли файл доступным и читаемым. Вместо поиска ошибок FileNotFoundError, вам нужно искать любые ошибки типа IOError:

try:

    f = open(‘new-music.mp3’)

    f.close()

except IOError:

    print(‘Файл недоступен’)

print(‘Файл доступен’)

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

def is_accessible(path, mode=‘r’):

    «»»

    Проверка, является ли файл или папка из `path`

    доступным для работы в предоставленным `mode` формате.

    «»»

    try:

        f = open(path, mode)

        f.close()

    except IOError:

        return False

    return True

Как альтернатива, вы можете использовать функцию os.access() из стандартной библиотеке для проверки того, существует ли файл и является ли он доступным в то же время. Это может быть похоже на использование функции path.exists(), если файл существует.

Использование open() и try ... except имеет некоторые преимущества, когда доходит до обработки файлов в Python. Это может помочь вам избежать накладок, вызванных определенными условиями существования файла:

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

Мы рассмотрим этот случай в конце руководства. Но перед этим, запрыгнем в еще одну кроличью нору. Рассмотрим еще один способ того, как проверить, существует ли файл в Python.

Пример проверки существования файла pathlib.Path.exists() (Python 3.4+)

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

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

Чтобы узнать, указывает ли путь на настоящий файл, вы можете использовать метод Path.exists(). Чтобы узнать, является путь файлом, или символической ссылкой, а не папкой, вам захочется воспользоваться Path.is_file().

Вот рабочий пример для обоих методов pathlib.Path:

import pathlib

path = pathlib.Path(‘music.mp3’)

print(path.exists()) # True

print(path.is_file()) # True

Как мы видим, этот подход по своему принципу схож с проверкой при помощи функций из модуля os.path.

Главное отличие в том, что pathlib предоставляет более чистый объекно-ориентированный интерфейс для работы с файловой системой. Вам больше не нужно работать с объектами str, представляющими пути файлов — вместо этого, вы обрабатываете объекты Path с релевантными методами и связанными с ними атрибутами.

Использование pathlib и преимущества объектно-ориентированного интерфейса может сделать ваш код обработки более читаемым и понятным. Не будем лгать и говорить, что это панацея. Но в ряде случаев это может помочь вам написать более “лучшую” версию программы Python.

Модуль pathlib также доступен как сторонний модуль с бэкпортом для PyPl, который работает на Python 2.x и 3.х Вы можете найти его здесь: pathlib2.

Подведем итоги проверки на наличие файла в Python

В данном руководстве мы сравнили три разных метода определения наличия или отсутствия файла в Python. Один метод также позволяет нам проверить, существует ли файл и является ли он доступным в то же время.

Конечно, имея в распоряжении три способа, вы можете подумать:

Какой способ проверки наличия файла при помощи Python является предпочтительнее?

В большинстве случаев, когда вам нужно проверить наличие файла, рекомендуется использование встроенного метода pathlib.Path.exists() на Python 3.4 и выше, или функцию os.path.exists() для Python 2.

Однако, есть одна важная оговорка…

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

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

Чтобы избежать такой ситуации, стоит опираться не только на вопрос “существует ли файл?”. Вместо этого, неплохо просто попытаться сразу выполнить желаемую операцию. Это также называется “easier to ask for forgiveness than permission” (EAFP) (проще просить прощения, чем разрешения). Такой подход часто рекомендуется при работе с Python.

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

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

Являюсь администратором нескольких порталов по обучению языков программирования Python, Golang и Kotlin. В составе небольшой команды единомышленников, мы занимаемся популяризацией языков программирования на русскоязычную аудиторию. Большая часть статей была адаптирована нами на русский язык и распространяется бесплатно.

E-mail: vasile.buldumac@ati.utm.md

Образование
Universitatea Tehnică a Moldovei (utm.md)

  • 2014 — 2018 Технический Университет Молдовы, ИТ-Инженер. Тема дипломной работы «Автоматизация покупки и продажи криптовалюты используя технический анализ»
  • 2018 — 2020 Технический Университет Молдовы, Магистр, Магистерская диссертация «Идентификация человека в киберпространстве по фотографии лица»

Если вы получили сообщение об ошибке «FileNotFoundError: [WinError 2] Система не может найти указанный файл», это означает, что по указанному вами пути нет файла.

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

Воссоздание ошибки

Давайте воссоздадим этот скрипт, где интерпретатор Python выдает FileNotFoundError.

В следующей программе мы пытаемся удалить файл, но мы предоставили путь, которого не существует. Python понимает эту ситуацию, как отсутствие файла.

import os

os.remove('C:workspacepythondata.txt')
print('The file is removed.')

В приведенной выше программе мы попытались удалить файл, находящийся по пути C:workspacepythondata.txt.

Консольный вывод:

C:workspacepython>dir data*
 Volume in drive C is OS
 Volume Serial Number is B24

 Directory of C:workspacepython

22-02-2019  21:17                 7 data - Copy.txt
20-02-2019  06:24                90 data.csv
               2 File(s)             97 bytes
               0 Dir(s)  52,524,586,329 bytes free

У нас нет файла, который мы указали в пути. Итак, при запуске программы система не смогла найти файл, что выдаст ошибку FileNotFoundError.

Как решить проблему?

Есть два способа обработки ошибки FileNotFoundError:

  • Используйте try-except и обработайте FileNotFoundError.
  • Убедитесь, что файл присутствует, и выполните соответствующую операцию с файлом.

В следующей программе мы использовали Try Except. Мы будем хранить код в блоке try, который может вызвать ошибку FileNotFoundError.

import os

try:
    os.remove('C:/workspace/python/data.txt')
    print('The file is removed.')
except FileNotFoundError:
    print('The file is not present.')

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

import os

if os.path.isfile('C:/workspace/python/data.txt'):
    print('The file is present.')
else:
    print('The file is not present.')

This div height required for enabling the sticky sidebar

Одна из стандартных проблем при работе с файлами — отсутствие необходимых файлов. Тот файл, который вам нужен, может находиться в другом месте, в имени файла может быть допущена ошибка, или файл может вообще не существовать. Все эти ситуации достаточно прямолинейно обрабатываются в блоках try-except.

Попробуем прочитать данные из несуществующего файла. Следующая программа пытается прочитать содержимое файла с текстом «Алисы в Стране чудес», но я не сохранил файл alice.txt в одном каталоге с файлом alice.py:

alice.py

filename = ‘alice.txt’

with open(filename) as f_obj:

. .contents = f_obj.read()

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

Traceback (most recent call last):

File «alice.py», line 3, in <module>

. .with open(filename) as f_obj:

FileNotFoundError: [Errno 2] No such file or directory: ‘alice.txt’

В последней строке трассировки упоминается FileNotFoundError: это исключение выдается в том случае, если Python не может найти открываемый файл. В данном примере функция open() порождает ошибку, и, чтобы обработать ее, блок try начинается перед строкой с вызовом open():

filename = ‘alice.txt’

try:

with open(filename) as f_obj:

contents = f_obj.read()

except FileNotFoundError:

. .msg = «Sorry, the file » + filename + » does not exist.»

. .print(msg)

В этом примере код блока try выдает исключение FileNotFoundError, поэтому Python ищет блок except для этой ошибки. Затем выполняется код этого блока, в результате чего вместо трассировки выдается доступное сообщение об ошибке:

Sorry, the file alice.txt does not exist.

Если файл не существует, программе больше делать нечего, поэтому код обработки ошибок почти ничего не добавляет в эту программу. Доработаем этот пример и посмотрим, как обработка исключений помогает при работе с несколькими файлами.

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

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

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

До начала

Перед выполнением любой из приведенных ниже команд убедитесь, что в вашей системе установлен Python 3. Откройте терминал и введите следующую команду:

python --version
# Python 3.9.5, my result

Если у вас есть версия 2.x, вам нужно будет использовать команду «python3». Ознакомьтесь с нашим руководством по установке Python, если у вас не установлен Python 3.

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

touch testfile.txt
mkdir testdirectory/ 
touch testdirectory/otherfile.txt

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

Примечание. Если вы используете Windows, настройте простую файловую структуру этого файла с помощью графического файлового менеджера.

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

pip install ipython

После этого вы получите доступ к красивой оболочке Python, просто набрав ipython.

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

Попробуйте, откройте и за исключением

Это самый простой вариант. Если вы попытаетесь открыть несуществующий файл, Python вызовет FileNotFoundError.

In [1]: open('im-not-here.txt')
---------------------------------------------------------------------------
FileNotFoundError: [Errno 2] No such file or directory: 'im-not-here.txt'

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

In [2]: try:
   ...:     file = open('im-not-here.txt')
   ...:     print(file) # File handler
   ...:     file.close()
   ...: except FileNotFoundError:
   ...:     print('Sorry the file we're looking for doesn' exist')
   ...:     exit()
   ...: 
Sorry the file we're looking for doesn't exist

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

Обратите внимание, что функция exit() будет выполняться только в случае возникновения исключения. Давайте посмотрим, что произойдет, когда искомый файл действительно существует.

In [2]: try:
   ...:     file = open('testfile.txt')
   ...:     print(file) # File handler
   ...:     file.close()
   ...: except FileNotFoundError:
   ...:     print('Sorry the file we're looking for doesn't exist')
   ...:     exit()
   ...: 
<_io.TextIOWrapper name="testfile.txt" mode="r" encoding='UTF-8'>

Обратите внимание, как мы закрываем файл сразу после того, как открыли его. Это считается хорошей практикой в ​​соответствии с Документация по Python.

Вызов file.write() без использования ключевого слова with или вызова file.close() может привести к тому, что аргументы file.write() не будут полностью записаны на диск, даже если программа завершится успешно.

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

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

In [3]: try:
   ...:     with open('testfile.txt') as file:
   ...:         print(file)
   ...:         # No need to close the file
   ...: except FileNotFoundError:
   ...:     print('Sorry the file we're looking for doesn't exist')
   ...:     exit()
   ...: 
   ...: 
<_io.TextIOWrapper name="testfile.txt" mode="r" encoding='UTF-8'>

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

os.path.exists()

ОС модуль предоставляет несколько функций для взаимодействия с операционной системой. Чтобы проверить, существует ли файл или папка, мы можем использовать функцию path.exists(), которая принимает путь к файлу или каталогу в качестве аргумента. Он возвращает логическое значение на основе существования пути.

Примечание. Путь — это уникальное расположение файла или каталога в файловой системе.

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

/home/daniel/.bashrc

Или с относительными путями, в зависимости от каталога, в котором вы запускаете скрипт:

.bashrc
# Running the script in my home folder

Вот несколько примеров использования функции os.path.exists(), работающей в каталоге, в котором расположены мои тестовые файлы:

In [1]: import os

In [2]: os.path.exists('testfile.txt')
Out[2]: True

In [3]: os.path.exists('testdirectory')
Out[3]: True

In [4]: os.path.exists('hey-i-dont-exist')
Out[4]: False

Как видите, он возвращает True при тестировании с файлом testfile.txt и папкой testdirectory и False, если файл не существует.

os.path.isfile()

Если вы хотите только доказать существование файла (а не каталога), вы должны вызвать функцию os.path.isfile().

In [1]: import os

In [2]: os.path.isfile('testfile.txt')
Out[2]: True

In [3]: os.path.isfile('testdirectory/')
Out[3]: False

In [4]: os.path.isfile('i-dont-even-exist')
Out[4]: False

In [5]: os.path.isfile('testdirectory/otherfile.txt')
Out[5]: True

Примечание. В UNIX все каталоги заканчиваются косой чертой (/), тогда как в Windows используется обратная косая черта ().

В приведенном выше коде функция isfile() возвращает False в двух случаях, давайте посмотрим, почему:

  • testdirectory/ — это каталог, поэтому он не считается файлом. Это не совсем так, поскольку в Linux все это файловый дескрипторно Python обрабатывает каталоги по-разному только для удобства (если вы попытаетесь открыть каталог, вы получите IsADirectoryError)
  • i-dont-even-exist указывает на файл, которого по иронии судьбы не существует

os.path.isdir()

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

In [1]: import os

In [2]: os.path.isdir('testfile.txt')
Out[2]: False

In [3]: os.path.isdir('testdirectory')
Out[3]: True

In [4]: os.path.isdir('anotherfile.txt')
Out[4]: False

Обратите внимание, как приведенные выше примеры возвращают False, даже если путь указывает на существующий файл.

Глоб

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

In [1]: import glob

In [2]: glob.glob('testfile.txt')
Out[2]: ['testfile.txt']

In [3]: glob.glob('testdirectory')
Out[3]: ['testdirectory']

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

Примечание. Если шаблон не соответствует, вы получите пустой список.

Учитывая, что мы можем передавать шаблоны в функцию glob, почему бы не проверить некоторые из ее основных преимуществ?

Код ниже получает все пути к файлам с расширением .txt и .py соответственно:

In [4]: glob.glob('*.txt')
Out[4]: ['testfile.txt']

In [5]: glob.glob('*.py')
Out[5]: 
['pathlib-exists.py',
 'list-dir.py',
 'glob-file.py',
 'open-except.py',
 'subprocess-test.py',
 'isfile.py',
 'exists.py',
 'isdir.py']

Использование класса пути

Класс пути — один из лучших способов работы с путями, поскольку он дает нам чистый интерфейс для работы с путями к файлам как с объектами.

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

Примечание. Для использования библиотеки pathlib вам понадобится Python 3.4 или выше.

Методы пути, которые вы будете использовать:

Проверить, существует ли путь

In [1]: from pathlib import Path

In [2]: Path('testfile.txt').exists()
Out[2]: True

In [3]: Path('im-not-here.txt').exists()
Out[3]: False

In [4]: Path('testdirectory').exists()
Out[4]: True

Работает так же, как os.path.exists().

Проверьте, указывает ли путь на файл

In [5]: Path('testfile.txt').is_file()
Out[5]: True

In [6]: Path('testdirectory').is_file()
Out[6]: False

Эквивалент os.path.isfile().

Проверьте, указывает ли путь на каталог

In [7]: Path('testfile.txt').is_dir()
Out[7]: False

In [8]: Path('testdirectory').is_dir()
Out[8]: True

Соответствует os.path.isdir().

подпроцесс

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

Примечание. Команда test работает только в Unix.

Следующие тестовые флаги выполнят работу:

  • test -e: проверить, существует ли путь
  • test -f: проверить, существует ли файл
  • test-d: проверить, существует ли папка

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

man test

Проверка пути с подпроцессом:

Код ниже определяет, существует ли путь, сравнивая код возврата подпроцесса с 0.

Помните, что в Linux, если процесс прошел успешно, он вернет ноль, а если нет, то вернет любой другой код.

In [1]: from subprocess import run

In [2]: run(['test', '-e', 'testfile.txt']).returncode == 0
Out[2]: True

In [3]: run(['test', '-e', 'im-not-here.txt']).returncode == 0
Out[3]: False

В первом операторе мы импортируем модуль подпроцесса, затем используем запустить функцию и получить его код возврата.

Проверка существования файла с подпроцессом

In [4]: run(['test', '-f', 'testfile.txt']).returncode == 0
Out[4]: True

In [5]: run(['test', '-f', 'testdirectory']).returncode == 0
Out[5]: False

Проверка каталога с подпроцессом:

In [6]: run(['test', '-d', 'testfile.txt']).returncode == 0
Out[6]: False

In [7]: run(['test', '-d', 'testdirectory']).returncode == 0
Out[7]: True

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

Подводить итоги

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

Наиболее просто это сделать:

  • Немедленное открытие и обработка файловых исключений
  • Использование функции exists() модулей os.path или pathlib.

В этом уроке вы узнали:

  • Как открыть файл и обработать исключения, если он не существует
  • Значение путей
  • 3 различных функции, которые предоставляет подмодуль os.path для проверки существования файла или папки.
  • Unix использует прямую косую черту (/), в то время как Windows использует обратную косую черту ()

Далее прочитайте: Что такое подпроцесс в Python? [5 Usage Examples]

In this tutorial, you’ll learn how do I check if a file exists or not in Python.

Whenever we work with files, sometimes we need to check whether the file is present on a given path before performing any operation.

For example, if you are trying to copy content from one file into another file. In this case, we need to check if both files exist before executing this operation. It will raise a FileNotFound exception if the file is not present on the disk. Python has multiple ways to check whether a file exists with or without exception (without using the try statement).

In this article, We will use the following three methods of an OS and pathlib module.

os.path module:

  • os.path.isfile('file_path'): Returns True if the path is a regular file.
  • os.path.exists('file_path'): Returns True if the path is a file, directory, or a valid symlink.
  • os.path.isdir('file_path'): Returns True if the path is a directory.

Pathlib module:

  • pathlib.Path('file_path').isfile(): Returns True if the path is a file.

Table of contents

  • os.path.isfile() Method to Check If File Exists
    • Example
  • pathlib.Path.isfile() Method to Check If File Exists
  • os.path.exists() Method to Check if File Exists
  • Check If File Exists in a Directory or Subdirectories
  • Check if Directory exists using os.path.isdir()
  • Race Condition
  • Summary

os.path.isfile() Method to Check If File Exists

For example, if you want to read a file to analyze the sales data to prepare a monthly report, we want to check whether we have a sales file with data in place to analyze it. If the file does not exist, we will need to create it.

The os.path module has some valuable functions on pathnames. Here we will see how to use the os.path module to check if a file exists.

  1. Important the os.path module

    This module helps us to work with file paths and directories in Python. Using this module, we can access and manipulate paths.

  2. Construct File Path

    A file path defines the location of a file or folder in the computer system. There are two ways to specify a file path.

    Absolute path: which always begins with the root folder. The absolute path includes the complete directory list required to locate the file. For example, /user/Pynative/data/sales.txt is an absolute path to discover the sales.txt. All of the information needed to find the file is contained in the path string.

    Relative path: which is relative to the program’s current working directory.

    To maintain uniformity across the operating system, use the forward-slash (/) to separate the path. It’ll work across Windows, macOS, and Unix-based systems, including Linux.

  3. Use os.path.isfile() function

    Use the os.path.isfile('file_path') function to check whether a file exists. Pass the file name or file path to this function as an argument. This function returns True if a file is present on the given path. Otherwise, it returns False.

Example

In this example, we are looking for sales.txt.

import os.path

# file to check
file_path = r'E:/demos/files_demos/account/sales.txt'

flag = os.path.isfile(file_path)
if flag:
    print(f'The file {file_path} exists')
else:
    print(f'The file {file_path} does not exist')
    # you can create it if required

Output:

The file E:/demos/files_demos/account/sales.txt exists

Note:

The os.path.isfile() will return True only when the given path is a file path. If the given path is a directory, it will return False. If you want to check for both file/directory then use the os.path.exists(file_path).

Example:

import os.path

# file
print(os.path.isfile(r'E:/demos/files_demos/account/sales.txt'))
# Output True

# Directory
print(os.path.isfile(r'E:/demos/files_demos/account/'))
# Output False

# Directory
print(os.path.exists(r'E:/demos/files_demos/account/'))
# Output True

Also, this is the simplest way to check if a file exists. However, just because the file existed when you checked doesn’t guarantee that it will be there when you need to open it because if many applications or users are using it, there is a chance it could get deleted or moved after your check.

pathlib.Path.isfile() Method to Check If File Exists

From Python 3.4 onwards, we can use the pathlib module, which provides a wrapper for most OS functions. This module offers classes representing filesystem paths with semantics appropriate for different operating systems.

The pathlib module allows you to manipulate files and directories using the object-oriented approach. Let’s see how to use the pathlib module to check if a file exists.

  • First, import pathlib module
  • Next, Use pathlib.Path('file_path') class to create a concrete path (location of the file). It will return the file path object.
  • At the end, execute the path.is_file() method to check if given file exists.

Example:

from pathlib import Path

file_path = r'E:/demos/files_demos/account/sales.txt'
# Path class

path = Path(file_path)

if path.is_file():
    print(f'The file {file_path} exists')
else:
    print(f'The file {file_path} does not exist')

os.path.exists() Method to Check if File Exists

This function returns True if the path is a regular file, directory, or a valid symlink. If the given path is a directory path instead of a file, it will still return True because it checks only for a valid path.

Example:

import os.path

file_path = r'E:/demos/files_demos/account/sales.txt'

flag = os.path.exists(file_path)
if flag:
    print(f'The file {file_path} exists')
else:
    print(f'The file {file_path} does not exist')

# directory
flag = os.path.exists(r'E:/demos/files_demos/account/')
if flag:
    print(f'The path exists')
else:
    print(f'path does not exist')

Output:

The file E:/demos/files_demos/account/sales.txt exists
The path exists

Check If File Exists in a Directory or Subdirectories

Sometimes we need to check whether the file is present in a given directory or its subdirectories. Let’s see this with an example.

Example: check if ‘sale.txt’ exists in the reports folder and its subfolders.

  • We need to use Python glob module.
  • Set recursive=True to search inside all subdirectories. It is helpful If we are not sure exactly in which folder our search term or file is located. it recursively searches files under all subdirectories of the current directory.
import glob

# glob to search sales.txt in account folder and all its subfolders
for file in glob.glob(r'E:demosreports/**/sales.txt', recursive=True):
    if file:
        print(file, 'exists')
    else:
        print('file not exists')

Output:

E:demosreportsaccountsales.txt exists

Check if Directory exists using os.path.isdir()

The os.path.isdir(path) function returns True if the path is a directory or a symlink to a directory.

Example:

import os.path

# returns True or False
if os.path.isdir(r'E:demosfiles'):
    print("Directory exist")
else:
    print("Directory not exist")

Output:

Directory exist

Race Condition

Using the try statement, you simply attempt to read your file, expecting it to be there, and if not, you can catch the exception and perform the fallback operation.

But if you want to check a file exists before you attempt to read it, if multiple threads or applications are using the same file, there is a chance they might delete it after your file check. Therefore, it will increase the risk of a race condition.

When you find a file exists and attempt to read it. But after your checking and before reading, if a file gets deleted (its existence changes), you will get an exception.

Race conditions are very hard to debug because there’s a tiny window in which they can cause your program to fail.

Summary

The os.path module provides the following three more functions to check if a file or directory exists.

  • os.path.isfile(path) – Returns True if the path is a regular file or a symlink to a file.
  • os.path.exists(path) – Returns True if the path is a file, directory, or a valid symlink.
  • os.path.isdir(path) – Returns True if the path is a directory or a symlink to a directory.

Pathlib module provides a pathlib.Path('file_path').isfile() function to check if the exists .

Python Exercises and Quizzes

Free coding exercises and quizzes cover Python basics, data structure, data analytics, and more.

  • 15+ Topic-specific Exercises and Quizzes
  • Each Exercise contains 10 questions
  • Each Quiz contains 12-15 MCQ

Работа с файлами – неотъемлемая составляющая взаимодействия с любым приложением с мало-мальски нормальным функционалом. И стандартная библиотека Python предоставляет возможность проверить файл на наличие в файловой системе.

В каких случаях это может пригодиться? Например, когда вы хотите удостовериться, что файл с данными доступен. Второй вариант – это профилактика того, чтобы файл не был записан повторно. Хотя функционал, который будет рассмотрен далее, может касаться и папок.

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

Сегодня мы разберем три специальные техники. Они используются разработчиками для того того, чтобы проверить, есть ли нужный файл, с помощью средств Python. Также мы приведем примеры кода и конкретные преимущества и недостатки. Заранее скажем, что лучшей или худшей нет. Они просто подходят для разных ситуаций. Да и просто необходимо уметь читать код. Поэтому изучить их придется.

Содержание

  1. Проверка наличия файла с помощью os.path.exists() и os.path.isfile()
  2. Использование функции open()параллельно с try … except
  3. Пример проверки существования файла pathlib.Path.exists()
  4. Выводы

Проверка наличия файла с помощью os.path.exists() и os.path.isfile()

Чаще всего для определения наличия файла используются методы exists() и isfile(), которые находятся в модуле os.path. Поскольку он находится в стандартной библиотеке, его не нужно дополнительно устанавливать.

Воспользоваться этими возможностями можно в Python 2 и Python 3.7. Как правило, их именно эти версии рекомендуют в первую очередь для проверки существования файлов.

Какая же функция самая простая для работы с файлами? Конечно же, exists(). Она содержит всего один аргумент – путь файла. Работа с функцией os.path.exists() осуществляется следующим образом. 

import os.path

 

check_file = os.path.exists('storage/music.mp3') # True

print(os.path.exists('нет-такого-файла.txt')) # False

 

# Проверяем если папка существует.

os.path.exists('storage') # True

Здесь мы проверили несколько путей на наличие. Как мы видим, мы получили True для файлов и папок с помощью этого вызова. Если вы хотите удостовериться, что этот путь указывает на файл, а не на папку, тогда можно воспользоваться функцией os.path.isfile(). Она по легкости ничуть не уступает предыдущей. 

import os.path

 

os.path.isfile('storage/music.mp3') # True

os.path.isfile('нет-такого-файла.txt') # False

os.path.isfile('storage') # False, папка существует но это не файл.

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

К данной технике мы обратимся немного позже. А сейчас попробуем рассмотреть еще один способ.

Использование функции open() параллельно с try … except

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

open('нет-такого-файла.txt')

    FileNotFoundError:

"[Errno 2] No such file or directory: 'нет-такого-файла.txt'"

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

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

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

try:

    f = open('нет-такого-файла.txt')

    f.close()

except FileNotFoundError:

    print('Файл не существует!')

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

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

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

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

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

try:

    f = open('new-music.mp3')

    f.close()

except IOError:

    print('Файл недоступен')

print('Файл доступен')

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

def is_accessible(path, mode='r'):

    """

    Проверка, является ли файл или папка из `path`

    доступным для работы в предоставленным `mode` формате.

    """

    try:

        f = open(path, mode)

        f.close()

    except IOError:

        return False

    return True

В качестве альтернативы, можно применять функцию os.access(). Чтобы ею воспользоваться, никаких дополнительных модулей устанавливать не нужно. Она доступна непосредственно в стандартной библиотеке.

С помощью функции os.access() можно проверить факт существования файла и его доступность. Это похоже на использование функции path.exists(), если файл есть в наличии. 

Использование open() и try … except имеет ряд положительных сторон, когда речь идет об обработке файлов в Python. Это позволяет не допустить сложностей, связанных с какими-то условиями наличия файла.

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

Давайте еще один вариант действий проанализируем.

Пример проверки существования файла pathlib.Path.exists()

Python 3.4 и выше включает модуль pathlib, представляющий объектно-ориентированную среду для работы с путями файлов и папок. Это значительно лучше, чем работать с путями в форме объектов строк. 

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

Чтобы проверить, ведет ли путь к этому файлу, можно воспользоваться методом Path.exists(). А чтобы узнать, не является ли путь файлом или символической ссылкой, тогда надо воспользоваться методом Path.is_file().

Вот пример, как это все работает. 

import pathlib

 

path = pathlib.Path('music.mp3')

print(path.exists()) # True

print(path.is_file()) # True

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

Существенное отличие в том, что pathlib предоставляет более чистую объектно-ориентированную среду для взаимодействия с файловой системой. Больше нет необходимости взаимодействовать с объемами str, которые представляют пути файлов. Напротив, необходимо лишь обрабатывать объекты Path с релевантными методами и атрибутами, имеющими связь с ними.

Задействование pathlib и положительные стороны объектно-ориентированного интерфейса способны значительно увеличить читаемость и понятность кода. Но не будем говорить о том, что это средство от всех бед. Конечно, всех проблем это не решает, но помогает существенно улучшить код.

Модуль pathlib может быть использован в качестве стороннего модуля с бэкпортом для PyPI, работающего на Python 2.x и 3.x.

Выводы

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

Естественно, имея в наличии три метода выполнения одной и той же задачи, вы можете подумать, о том, какой из них лучше. В подавляющем числе случаев, при необходимости проверки существования файла, рекомендуется использовать метод pathlib.Path.exists() на Python 3.4 и выше, либо функцию os.path.exists() для Python 2 версии.

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

Чтобы не допустить их, не нужно проверять существование файла. Хорошо просто попытаться сразу выполнить операцию, которую нужно. Этот принцип называется «проще просить прощения, чем разрешения» и очень часто рекомендуется специалистами по Python новичкам.

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

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

Оцените качество статьи. Нам важно ваше мнение:

0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии

А вот еще интересные материалы:

  • Яшка сломя голову остановился исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного где ошибка
  • Ошибка оформления заказа бургер кинг
  • Ошибка отсутствие отрицательных остатков сумм ндс предъявленных поставщиками как исправить