Могу ли я использовать сообщение об ошибке для классификации ошибки?

Я пишу обёртку над несколькими архивами наподобие Patool. Я хочу оповестить пользователя, если архив (какой бы он не был) требует пароль для распаковки, а также если пароль не верен. Для этого я использую пользовательские типы исключений

class WrongPasswordError(ValueError):
    ''' Raised when the password for unpacking the archive is incorrect. '''

class PasswordRequiredError(ValueError):
    ''' Raised when a password is required to unpack an archive, but it is not specified.  '''

Таким образом, когда я пытаюсь распаковать Rar архив, я использую следующий перехват исключений:

def extract_file(self, file_path, output_path, password=None):
        try:
            if password is not None:
                self.archive_obj.extract(file_path, path=output_path, pwd=password)
            else:
                self.archive_obj.extract(file_path, path=output_path)
            return True
        except rarfile.PasswordRequired as e:
            raise PasswordRequiredError(str(e))
        except rarfile.RarWrongPassword as e:
            raise WrongPasswordError(str(e))

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

# фрагмент кода Zipfile:
...
if h != check_byte:
    raise RuntimeError("Bad password for file %r" % zipinfo.orig_filename)
...


# другой фрагмент кода
...
if not pwd:
    raise RuntimeError("File %r is encrypted, password "
                       "required for extraction" % name)
...

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

def extract_file(self, file_path, output_path, password=None):
        try:
            if password is not None:
                self.archive_obj.extract(file_path, path=output_path, pwd=password)
            else:
                self.archive_obj.extract(file_path, path=output_path)
        except RuntimeError as e:
            stringed = str(e)
            if 'password required for extraction' in stringed:
                raise PasswordRequiredError(stringed)
            elif 'Bad password' in stringed:
                raise WrongPasswordError(stringed)
            else:
                raise

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


Есть ли более чистый и питонический способ решить проблему с разделением исключений?


Ответы (0 шт):