Обработка исключений на этапе настройки Python Context Manager - PullRequest
1 голос
/ 26 сентября 2019

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

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

Maps не закрывает базовый файловый объект, поэтому я пытаюсь исправить это в моем подклассе, указав __enter__ и__exit__.

class BetterMaps(Maps):
    def __enter__(self):
        return self
    def __exit__(self, type, value, traceback):
        self.data.close()

Итак, мы можем сделать что-то вроде:

with BetterMaps(name, releaseversion) as bettermaps:
    do_work_here(bettermaps)

и объект файла действительно закрыт. Однако , это работает только тогда, когда базовый файл действительно существует: если файл не существует, то AssertionError или NoMapsHereError повышается, в зависимости от конкретных обстоятельств.В парадигме, которую я использовал ранее, я создал Maps что-то вроде:

try:
    maps = Maps(name, releaseversion)
except (AssertionError, NoMapsHereError) as e:
    proceed = False
else:
    proceed = True

if proceed:
    do_work_here(maps)

, который обрабатывал исключения в случае отсутствия данных для чтения.

Теперь яЯ не уверен, как встроить это поведение в синтаксис менеджера контекста, который я использую.До сих пор я пытался изменить __enter__ для регистрации существования данных и вернуть False, если нет:

class BetterMaps(Maps):
    def __enter__(self):
        try:
            self.data_dne = False
            return self
        except (NoMapsHereError, AssertionError):
            self.data_dne = True
            return False
    def __exit__(self, type, value, traceback):
        if self.data_dne:
            pass
        else:
            self.data.close()

with BetterMaps(name, releaseversion) as bettermaps:
    if not bettermaps:
        pass
    else:
        do_work_here(bettermaps)

с намерением, что в случае сбоя установки (данные не могутне будет загружен), bettermaps будет принимать значение False, которое будет обходить do_work_here().Это не работает, и AssertionError все еще поднят.Разве ошибки, возникающие в __init__, не подчиняются логике в __enter__?

В более широком смысле, есть ли предпочтительный способ обработки случаев, когда что-то в __init__ ломается?Я понимаю, что в моем случае я мог попытаться восстановить имя файла, к которому осуществляется доступ, и остановиться, если файл не существует;но я бы настоятельно предпочел бы не делать этого, так как это усложнит мою кодовую базу.Обратная связь приветствуется.

...