2010-03-26 10 views
19

Jaki jest właściwy sposób sprawdzania błędów w klasie? Zgłaszanie wyjątków? Ustawienie "błędów" słownika zmiennych instancji zawierającego wszystkie błędy i zwrócenie ich?Właściwy sposób w języku Python do zgłaszania błędów podczas ustawiania zmiennych

Czy źle wydrukować błędy z zajęć? Czy muszę zwracać Fałsz, jeśli zgłaszam wyjątek?

Chcę się tylko upewnić, że wszystko dobrze. Poniżej znajduje się przykładowy kod:

@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() 
+1

Zbyt wiele rzeczy o nazwie "hasło" w tym kodzie. (pierwsza funkcja, druga funkcja i argument do drugiej funkcji.) pyflakes będą twoim przyjacielem. – keturn

+0

@keturn: jest to wzorzec pokazany w dokumentach dla funkcji 'property()'. Spójrz na [przykład kodu w dokumentach, które używają '.setter' decorator] (https://docs.python.org/3/library/functions.html#property). Wewnątrz metody ustawiającej "password" jest zmienną lokalną (parametr). Inne nazwy znajdują się w innym obszarze nazw (należą do klasy). – jfs

Odpowiedz

28

Twój kod wykracza poza kontekst, więc nie jest oczywistym wyborem.Po kilka porad:

  • Nie używaj NameError wyjątku, jest on stosowany tylko wtedy, gdy nazwa, jako wyjątek sam powiedział, jest nie znajduje się w zasięgu lokalnym lub globalnym, użyj ValueError lub TypeError jeśli dotyczy wyjątków wartość lub typ parametru;

  • Nie drukuj komunikatów o błędach. Podnieść znaczące wyjątki ze znaczącym komunikatem o błędzie:

    raise ValueError("password must be longer than 6 characters") 
    
  • Zwracanie wartości z seter jest bez znaczenia, gdy przypisanie nie jest wyrazem, czyli nie można sprawdzić wartość cesji:

    if (user.password = 'short'): ... 
    
  • Wystarczy podnieść wyjątek w ustawieniu i pozwolić kodowi, który ustawił właściwość, obsłużyć go.

Przykład:

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 

również spojrzeć this forms handling library istnieje validators, here an example, to podmioty w ich własnych: mogą być ustawione dynamicznie z większą kontrolą i kodu mniej sprzężony, ale może to jest o wiele więcej niż potrzebujesz.

+1

To było naprawdę pomocne. Dziękuję Ci. – ensnare

+0

@mg, Świetna wiadomość (i świetne inicjały!) Ogólnie rzecz biorąc, ale martwię się o przykład na końcu. Wygląda na to, że wymyśliłeś dekoratora 'hasło', którego użycie jest dość dziwne; masz na myśli '@ property' i nazwać pierwszą metodę' password'? Ponadto musisz użyć klas nowego stylu, jeśli chcesz użyć właściwości, tzn. Zmienić pierwszy wiersz przykładu na "klasa Test (obiekt):" lub dziedziczyć z innej klasy w nowym stylu. (Nawet jeśli nie korzystałeś jeszcze z właściwości, powinieneś używać klas w nowym stylu.) –

+0

@Mike Graham: Cholera, zmęczenie może odgrywać złe dowcipy. masz prawo do nazewnictwa właściwości, dokładna forma jest używana pierwotnie przez ensare, wolę stare dobre 'password = własność (...)' ale byłbym spójny z ensare bez znajomości nowej składni 2.6. Druga obserwacja nie jest prawdą: właściwości mogą być używane ze starymi klasami stylu –

10

Standardowym sposobem sygnalizowania błędu w pythonie jest zgłoszenie wyjątku i umożliwienie obsługi go przez kod wywołujący. Pozwól, aby TypError & TypeError był kontynuowany lub przechwytuj i podnieś zdefiniowany wyjątek InvalidPassword.

Mimo że można przywrócić flagę sukcesu/błędu lub kod błędu z funkcji tak jak dotychczas, nie jest to zalecane - dzwoniący może łatwo zapomnieć o sprawdzeniu zwracanej wartości i utracie błędów. Poza tym zwracasz wartość z ustawiacza właściwości - nie ma to znaczenia w Pythonie, ponieważ przypisania nie są wyrażeniami i nie mogą zwracać wartości.

Nie powinieneś nigdy drukować wiadomości dla użytkownika podczas obsługi wyjątków - a co, jeśli później chcesz użyć tej funkcji lub klasy w programie GUI? W takim przypadku twoje polecenie wydruku nie będzie miało miejsca do drukowania. Rejestrowanie błędu w pliku dziennika (przy użyciu modułu logowania Pythona) jest często pomocne w debugowaniu.

4

Generalnie powinieneś wskazywać błędy propagujące się za pomocą wyjątków. Jeśli odkryjesz błąd przez coś, co właśnie sprawdziłeś, i możesz sobie z tym poradzić natychmiast, nie ma potrzeby zgłaszania wyjątku.

W szczególnym przypadku settera, na przykład, powrót False lub cokolwiek innego nie pomoże. Ustawienie zmiennych instancji, które musisz sprawdzić, jest bardzo nieoptymalne, ponieważ wtedy możesz pominąć błąd w wypadku.

print zazwyczaj nie jest dobrą odpowiedzią na błąd. W tym przypadku wygląda na to, że chcesz poinformować użytkownika końcowego, że potrzebuje innego hasła. Wygląda na to, że powinieneś wywołać metodę, która powoduje, że strona internetowa z formularzem wyjaśnia użytkownikowi, co poszło nie tak; możesz wywołać metodę, która robi to w twojej klasie lub podnieść wyjątek, który będzie się rozprzestrzeniał i ostatecznie zostanie złapany i użyty w tym celu. (To jest ogólna rada, nie wiem wystarczająco dużo o Pylons, żeby ci powiedzieć, jak tego chcesz.)

Nie powinieneś podnosić własnych wyjątków od NameError. NameError prettymuch zawsze wskazuje na literówkę w twoim programie i jako taki zwykle nie chcesz go złapać. Łapiąc ją, wprowadzasz niepotrzebną niepewność do programu. Wygląda na to, że może to być coś bardziej podobnego do podklasy (012). Nie mam pojęcia, dlaczego sprawdzasz TypeError. Powinieneś zawsze rozumieć, co spowodowałoby wyjątek, który złapałeś. Jeśli to zrobisz w tym przypadku, to świetnie; Nie mogę się dowiedzieć, jaki błąd mógłby podnieść TypeError, z którym mógłbyś sobie poradzić, podpowiadając użytkownika.

Twoja technika otrzymywania hasła w postaci zwykłego tekstu i przechowywania jego skrótu md5 nie jest bardzo bezpieczna. Powinieneś sprawdzić coś w stylu AuthKit, które może uczynić ten proces bezpieczniejszym i abstrakcyjnym.

Powiązane problemy