Правильный способ в Python вызывать ошибки при установке переменных - PullRequest
25 голосов
/ 26 марта 2010

Как правильно выполнять проверку ошибок в классе? Возникают исключения? Задать экземпляр переменной словарь «ошибки», содержащий все ошибки, и вернуть его?

Разве плохо печатать ошибки из класса? Нужно ли возвращать False, если я выдвигаю исключение?

Просто хочу убедиться, что я все делаю правильно. Ниже приведен пример кода:

@property
def password(self):
    return self._password

@password.setter
def password(self,password):
    # Check that password has been completed
    try:
        # Check that password has a length of 6 characters
        if (len(password) < 6):
            raise NameError('Your password must be greater \
                             than 6 characters')

    except NameError:
        print 'Please choose a password'
        return False

    except TypeError:
        print 'Please choose a password'
        return False                                                                                                                                

    #Set the password
    self._password = password

    #Encrypt the password
    password_md5 = md5.new()
    password_md5.update(password)
    self._password_md5 = password_md5.hexdigest()

Ответы [ 3 ]

40 голосов
/ 26 марта 2010

Ваш код находится вне контекста, поэтому не является правильным выбором. Следуя некоторым советам:

  • Не использовать NameError исключение, оно используется только в том случае, если имя, как само исключение, не найдено в локальной или глобальной области, используйте ValueError или TypeError, если это исключение касается значения или типа параметра;

  • Не печатать сообщения об ошибках. Вызовите значимые исключения со значимым сообщением об ошибке:

    raise ValueError("password must be longer than 6 characters")
    
  • Возвращать значение из установщика бессмысленно, пока присваивание не является выражением, т.е. вы не можете проверить значение присваивания:

    if (user.password = 'short'): ...
    
  • Просто вызовите исключение в установщике и позвольте коду, который устанавливает свойство, обработать его.

* +1025 * Пример:
class Test:

    minlen = 6

    @property
    def password(self):
        return self._password

    @password.setter
    def password(self, value):
        if not isinstance(value, basestring):
            raise TypeError("password must be a string")
        if len(value) < self.minlen:
            raise ValueError("password must be at least %d character len" % \
                                 self.minlen)
        self._password = value

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

10 голосов
/ 26 марта 2010

Стандартный способ сообщить об ошибке в python - вызвать исключение и разрешить его вызывающему коду. Либо позвольте NameError & TypeError продолжить работу вверх, либо перехватите их и вызовите исключение InvalidPassword, которое вы определяете.

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

Вы также никогда не должны печатать сообщение для пользователя при обработке исключений - что если вы позже захотите использовать функцию или класс в программе с графическим интерфейсом? В этом случае вашему заявлению на печать будет некуда печатать. Регистрация ошибки в лог-файл (с использованием модуля журналирования Python) часто полезна для отладки.

4 голосов
/ 26 марта 2010

Как правило, вы должны указывать ошибки, которые распространяются с помощью исключений. Если вы обнаружили ошибку по чему-то, что вы только что проверили, и вы можете немедленно устранить ее, нет необходимости выдавать исключение.

В частном случае установки, например, возврат False или что-то еще не поможет. Установка переменных экземпляра, которые вы должны проверить, является очень неоптимальной, поскольку с тех пор вы можете пропустить ошибку при аварии.

print обычно не является хорошим ответом на ошибку. В этом случае кажется, что вы хотите сказать конечному пользователю, что ему нужно использовать другой пароль. Похоже, вы должны вызвать метод, который заставляет веб-страницу с формой объяснить пользователю, что пошло не так; Вы можете вызвать метод, который делает это в вашем классе, или вызвать исключение, которое будет распространяться и в конечном итоге будет перехвачено и использовано для этой цели. (Это общий совет. Я не знаю достаточно о Pylons, чтобы рассказать вам, как он этого хочет.)

Вы не должны поднимать свои NameError исключения. NameError prettymuch всегда указывает на опечатку в вашей программе, и поэтому вы обычно не хотите ее отлавливать. Поймав это, вы вносите ненужную неопределенность в программу. Похоже, это может быть что-то более похожее на ValueError или его подкласс (class InvalidPasswordError(ValueError): pass).

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

Ваша техника получения пароля в виде открытого текста и хранения его хеша md5 не очень безопасна. Вам следует рассмотреть что-то вроде AuthKit, которое может сделать этот процесс более безопасным и абстрагированным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...