Проверка стандартной ошибки Python
У меня вопрос относительно проверки ошибок в 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)
Это то, что я обычно делал, хотя одно и то же IOException было бы поставлено Python, если файл не существует, даже если я его не поднимаю.
ii) Используйте assert, чтобы проверить предварительное условие:
assert os.path.exists(filepath), 'File does not exist: %s' % filepath
Использование утверждений, по-видимому, является "стандартным" способом проверки пре/постусловий, поэтому у меня возникает соблазн использовать их. Тем не менее, возможно, что эти утверждения отключены, когда во время выполнения используется флаг -o, что означает, что эта проверка может быть отключена, и это кажется рискованным.
iii) Не обрабатывайте предварительное условие вообще
Это связано с тем, что если путь к файлу не существует, в любом случае генерируется исключение, и сообщение об исключении будет достаточно подробным для того, чтобы пользователь знал, что файл не существует.
Мне просто интересно, какая из перечисленных выше - стандартная практика, которую я должен использовать для своих кодов.
Ответы
Ответ 1
Если все, что вы хотите сделать, это поднять исключение, используйте опцию 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
-block.
В Python 2.5 вы можете использовать синтаксис with
, если префикс script с
from __future__ import with_statement
Ответ 2
Определенно не используйте assert. Утверждения должны только терпеть неудачу, если код неверен. Внешние условия (например, отсутствующие файлы) не должны проверяться с помощью утверждений.
Как отмечали другие, утверждения могут быть отключены.
Формальная семантика утверждения:
-
Условие может быть или не быть оценено (поэтому не полагайтесь на побочные эффекты выражения).
-
Если условие истинно, выполнение продолжается.
-
undefined что происходит, если условие ложно.
Подробнее об этой идее.
Ответ 3
Далее следует пример ~ 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: Нет такого файла или каталога
Ответ 4
Я думаю, вы должны пойти со смесью iii) и i). Если вы знаете, что этот python будет генерировать исключение (т.е. Случай iii), то пусть это сделает python. Если есть другие предпосылки (например, требуемые вашей бизнес-логикой), вы должны бросить собственные исключения, возможно, даже получить из Exception
.
Использование утверждений слишком хрупкое imho, потому что они могут быть отключены.