Стандартная практика проверки ошибок Python - PullRequest
14 голосов
/ 16 мая 2010

У меня есть вопрос, касающийся проверки ошибок в Python. Допустим, у меня есть функция, которая принимает путь к файлу в качестве ввода:

def myFunction(filepath):
    infile = open(filepath)
    #etc etc...

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

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

i) Проверить с помощью оператора if:

if not os.path.exists(filepath):
    raise IOException('File does not exist: %s' % filepath)

Так я обычно и делаю, хотя Python выдает такое же исключение IOException, если файл не существует, даже если я его не поднимаю.

ii) Используйте assert для проверки предварительного условия:

assert os.path.exists(filepath), 'File does not exist: %s' % filepath

Использование утверждений представляется «стандартным» способом проверки предварительных / постусловий, поэтому я испытываю желание использовать их. Однако возможно, что эти утверждения отключены, когда во время выполнения используется флаг -o, что означает, что эта проверка потенциально может быть отключена, и это кажется рискованным.

iii) Не выполняйте предварительное условие вообще

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


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

Ответы [ 4 ]

15 голосов
/ 16 мая 2010

Если все, что вы хотите сделать, это вызвать исключение, используйте опцию iii:

def myFunction(filepath):
    with open(filepath) as infile:
        pass

Чтобы обрабатывать исключения особым образом, используйте блок try...except:

def myFunction(filepath):
    try:
        with open(filepath) as infile:
            pass
    except IOError:
        # special handling code here

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

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

В Python 2.5 вы можете использовать синтаксис with, если вы предварите свой сценарий

from __future__ import with_statement
4 голосов
/ 16 мая 2010

Определенно не используйте assert. Утверждения должны проваливаться, только если код неправильный. Внешние условия (например, отсутствующие файлы) не должны проверяться с помощью утверждений.

Как уже отмечали другие, утверждения можно отключить.

Формальная семантика assert:

  1. Условие может оцениваться или не оцениваться (поэтому не полагайтесь на побочные эффекты выражения).

  2. Если условие истинно, выполнение продолжается.

  3. Не определено, что произойдет, если условие ложно.

Подробнее об этой идее .

3 голосов
/ 16 мая 2010

Следующее следует из примера ~ unutbu. Если файл не существует или при любом другом типе ошибки ввода-вывода, имя файла также передается в сообщении об ошибке:

path = 'blam'
try:
    with open(path) as f:
        print f.read()
except IOError as exc:
    raise IOError("%s: %s" % (path, exc.strerror))

=> IOError: blam: Нет такого файла или каталога

1 голос
/ 16 мая 2010

Я думаю, что вы должны пойти с сочетанием III) и I). Если вы точно знаете, что python сгенерирует исключение (то есть, случай iii), то пусть Python сделает это. Если есть какие-то другие предварительные условия (например, требуемые вашей бизнес-логикой), вы должны выбросить собственные исключения, возможно, даже полученные из Exception.

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

...