python как безопасно обрабатывать исключение внутри контекстного менеджера
думаю, я читал, что исключения внутри with
не допускать __exit__
для правильного вызова. Если я ошибаюсь, простите мое невежество.
Итак, у меня есть псевдо-код здесь, моя цель-использовать контекст блокировки, который при __enter__
регистрирует начало datetime и возвращает идентификатор блокировки, а при __exit__
записывает конец datetime и освобождает блокировку:
def main():
raise Exception
with cron.lock() as lockid:
print('Got lock: %i' % lockid)
main()
как я могу по-прежнему вызывать ошибки в дополнение к существующему контексту безопасно?
примечание: Я намеренно поднимаю базовое исключение в этом псевдо-коде, поскольку я хочу безопасно выйти из любого исключения, а не только ожидаемых исключений.
Примечание: альтернативные / стандартные методы предотвращения параллелизма не имеют значения, я хочу применить эти знания к любому общему контекстному управлению. я не знаю, имеют ли разные контексты разные причуды.
PS. Это finally
блок актуален?
1 ответов
The __exit__
метод называется как обычно если диспетчер контекста нарушен исключением. Фактически, параметры передаются в __exit__
все имеют отношение к обработке этого дела! От документы:
object.__exit__(self, exc_type, exc_value, traceback)
закройте контекст выполнения, связанный с этим объектом. Параметры описывают исключение, вызвавшее выход из контекста. Если контекст был завершен без исключения, все три аргумента будут Никто.
если предоставлено исключение, и метод хочет подавить исключение (т. е. предотвратить его распространение), он должен вернуть значение true. В противном случае исключение будет обработано нормально при выходе из этого метода.
отметим, что
__exit__()
методы не должны перезапускать переданное исключение; это ответственность вызывающего абонента.
так что вы можете видеть, что __exit__
метод будет выполнен, а затем, по умолчанию, любой исключение будет повторно поднято после выход из контекстного менеджера. Вы можете проверить это самостоятельно, создав простой менеджер контекста и разбив его за исключением:
DummyContextManager(object):
def __enter__(self):
print('Entering...')
def __exit__(self, exc_type, exc_value, traceback):
print('Exiting...')
# If we returned True here, any exception would be suppressed!
with DummyContextManager() as foo:
raise Exception()
когда вы запускаете этот код, вы должны видеть все, что хотите (может быть не в порядке, так как print
имеет тенденцию заканчиваться в середине tracebacks):
Entering...
Exiting...
Traceback (most recent call last):
File "C:\foo.py", line 8, in <module>
raise Exception()
Exception