2010-03-26 19 views
19

Cách thích hợp để kiểm tra lỗi trong một lớp là gì? Tăng ngoại lệ? Thiết lập một từ điển biến từ điển "lỗi" có chứa tất cả các lỗi và trả về nó?Cách thích hợp trong Python để tăng lỗi trong khi thiết lập các biến

Có thể in các lỗi từ một lớp không? Tôi có phải trả lại Sai nếu tôi đang đưa ra một ngoại lệ không?

Chỉ muốn đảm bảo rằng tôi đang làm đúng. Dưới đây là một số mã mẫu:

@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

Quá nhiều thứ có tên là 'mật khẩu' trong mã đó. (chức năng đầu tiên, hàm thứ hai, và đối số cho hàm thứ hai.) pyflakes sẽ là bạn của bạn. – keturn

+0

@keturn: nó là một mẫu được hiển thị trong tài liệu cho hàm 'property()'. Hãy xem [ví dụ mã trong các tài liệu sử dụng 'decorator' .setter] (https://docs.python.org/3/library/functions.html#property). Bên trong phương thức setter 'password' là một biến cục bộ (tham số). Các tên khác nằm trong một không gian tên khác (chúng thuộc về lớp). – jfs

Trả lời

28

Mã của bạn nằm ngoài ngữ cảnh, vì vậy không rõ ràng là lựa chọn đúng đắn.Sau một số lời khuyên:

  • Không sử dụng NameError ngoại lệ, nó chỉ được sử dụng khi một cái tên, như là ngoại lệ riêng của mình cho biết, không tìm thấy trong phạm vi địa phương hay toàn cầu, sử dụng ValueError hoặc TypeError nếu những mối quan tâm ngoại lệ giá trị hoặc loại tham số;

  • Không in thông báo lỗi. Nâng cao ngoại lệ có ý nghĩa với một thông báo lỗi có ý nghĩa:

    raise ValueError("password must be longer than 6 characters") 
    
  • Trả về một giá trị từ một setter là vô nghĩa trong khi nhiệm vụ không phải là một biểu hiện, nghĩa là bạn không thể kiểm tra giá trị của một bài tập:

    if (user.password = 'short'): ... 
    
  • Chỉ cần tăng một ngoại lệ trong setter và để cho mã mà thiết lập thuộc tính xử lý nó.

Ví dụ:

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 

Nhìn cũng tại this forms handling library, có sự xác nhận, here an example, là các đơn vị trong riêng của họ: họ có thể được thiết lập tự động với điều khiển cao hơn và mã ít cùng, nhưng có lẽ đây là nhiều hơn bạn cần.

+1

Điều này thực sự hữu ích. Cảm ơn bạn. – ensnare

+0

@mg, Bài đăng tuyệt vời (và viết tắt tuyệt vời!) Tổng thể, nhưng tôi lo ngại về ví dụ ở cuối. Bạn dường như đã tạo nên một trang trí 'password', việc sử dụng nó khá kỳ quặc; bạn có nghĩa là '@ property' và đặt tên cho phương thức đầu tiên là' password'? Ngoài ra, bạn sẽ phải sử dụng các lớp kiểu mới nếu bạn muốn sử dụng các thuộc tính, tức là thay đổi dòng đầu tiên của ví dụ thành 'class Test (object):' hoặc kế thừa từ một số lớp kiểu mới khác. (Ngay cả khi bạn chưa sử dụng các thuộc tính, bạn nên sử dụng các lớp kiểu mới.) –

+0

@Mike Graham: damn, mệt mỏi có thể chơi những trò đùa tồi tệ. bạn thích hợp cho việc đặt tên thuộc tính, form chính xác là cái được sử dụng ban đầu bởi ensare, tôi thích cái cũ 'password = property (...)' nhưng tôi sẽ kết hợp với ensare mà không thực sự biết cú pháp 2.6 mới. Quan sát thứ hai là không đúng: các thuộc tính có thể được sử dụng với các lớp kiểu cũ –

10

Cách tiêu chuẩn báo hiệu lỗi trong python là tăng ngoại lệ và để mã gọi xử lý. Cho phép NameError & LoạiError mang lên trên hoặc bắt chúng và tăng ngoại lệ InvalidPassword mà bạn xác định.

Mặc dù có thể trả lại cờ thành công/lỗi hoặc mã lỗi từ chức năng như bạn đã làm, nhưng không được khuyến nghị - người gọi dễ quên kiểm tra giá trị trả lại và lỗi bị mất. Bên cạnh đó bạn đang trả về một giá trị từ một setter thuộc tính - điều này là vô nghĩa trong Python vì các bài tập không phải là các biểu thức và không thể trả về một giá trị.

Bạn cũng không bao giờ in thư cho người dùng trong xử lý ngoại lệ của mình - điều gì sẽ xảy ra nếu sau này bạn muốn sử dụng hàm hoặc lớp trong chương trình GUI? Trong trường hợp đó, bản in của bạn sẽ không có nơi nào để in. Việc ghi nhật ký lỗi vào một logfile (sử dụng mô đun ghi nhật ký của Python) thường hữu ích cho việc gỡ lỗi.

4

Nói chung, bạn nên chỉ ra lỗi truyền bá bằng cách sử dụng ngoại lệ. Nếu bạn phát hiện ra lỗi do một cái gì đó bạn vừa kiểm tra và bạn có thể xử lý nó ngay lập tức, không cần phải đưa ra một ngoại lệ.

Trong trường hợp cụ thể của người đặt hàng, ví dụ: trả lại False hoặc bất kỳ điều gì khác sẽ không giúp ích gì. Đặt các biến mẫu bạn phải kiểm tra là rất tối ưu, vì vậy bạn có thể bỏ lỡ một lỗi do tai nạn.

print thường không phản hồi tốt với lỗi. Trong trường hợp này, có vẻ như bạn muốn nói với người dùng cuối rằng họ cần sử dụng một mật khẩu khác. Có vẻ như bạn nên gọi một phương thức khiến trang web có biểu mẫu giải thích cho người dùng điều gì đã xảy ra; bạn có thể gọi phương thức thực hiện điều đó trong lớp của bạn hoặc đưa ra một ngoại lệ sẽ lan truyền và cuối cùng bị bắt và sử dụng cho mục đích đó. (Đây là lời khuyên chung. Tôi không biết đủ về giá treo để cho bạn biết nó muốn bạn làm điều này như thế nào.)

Bạn không nên tự mình tăng NameError ngoại lệ. NameError prettymuch luôn luôn chỉ ra một lỗi đánh máy trong chương trình của bạn, và như vậy bạn thường không muốn bắt nó. Bằng cách bắt nó, bạn giới thiệu sự không chắc chắn không cần thiết vào một chương trình. Điều này có vẻ như nó có thể là một cái gì đó giống như ValueError hoặc một phân lớp của chúng (class InvalidPasswordError(ValueError): pass).

Tôi không hiểu tại sao bạn kiểm tra TypeError. Bạn nên luôn luôn hiểu những gì sẽ gây ra một ngoại lệ bạn bị bắt. Nếu bạn làm trong trường hợp này, điều đó thật tuyệt; Tôi không thể tìm ra lỗi nào sẽ tăng TypeError mà bạn có thể xử lý một cách thỏa đáng bằng cách nhắc người dùng.

Kỹ thuật nhận mật khẩu của bạn trong văn bản thô và lưu trữ hàm băm md5 của nó không an toàn lắm. Bạn nên nhìn vào một cái gì đó giống như AuthKit có thể làm cho quá trình này an toàn hơn và trừu tượng hơn.

Các vấn đề liên quan