2013-04-20 31 views
16

Làm cách nào để xử lý tất cả ngoại trừ một ngoại lệ?Xử lý tất cả trừ một ngoại lệ

try: 
    something 
except NoChildException: 
    raise NoChildException 
except: 
    pass 
+4

Câu trả lời đơn giản: Không. Thực tiễn không tốt để bắt tất cả các ngoại lệ, vì bạn sẽ có xu hướng bắt được những cái bạn không có ý định, làm mờ các lỗi. Chỉ có một số ít trường hợp hợp pháp để làm một việc như vậy. –

+2

Bạn dường như đã trả lời câu hỏi của riêng bạn. Cho chúng tôi biết lý do bạn không hài lòng với những gì bạn có. –

+0

@ Robᵩ Không hoàn toàn, ví dụ của anh ta sẽ tạo một ngoại lệ * mới *, chứ không phải làm lại cái cũ. –

Trả lời

24

Câu trả lời chỉ đơn giản là làm raise:

try: 
    ... 
except SomeException: 
    raise 
except: 
    ... 

raise mà không cần bất kỳ biểu hiện sau nó sẽ đơn giản tăng ném ngoại lệ cuối cùng (ngay cả khi nó được xử lý!). Nó tương đương với:

except SomeException as e: 
    raise e 

Nếu bạn nghĩ rằng ngoại lệ khác có thể được ném trong khối catch (rõ ràng là không thể trong trường hợp này), bạn nên sử dụng định dạng sau để đảm bảo bạn lại nâng cao ngoại lệ đúng.

Tuy nhiên, như đã nêu trong bình luận của tôi:

câu trả lời đơn giản: Không. Thực tiễn không tốt để nắm bắt tất cả các trường hợp ngoại lệ , vì bạn sẽ có xu hướng bắt những người bạn không có ý định, lỗi che khuất. Chỉ có một số lượng nhỏ các trường hợp hợp pháp để thực hiện một việc như vậy.

Chỉ cần nắm bắt các lỗi mà bạn cho rằng mã của mình có thể bị ném và bạn biết cách xử lý và để lại bất kỳ lỗi nào khác. Nếu bất cứ điều gì khác xảy ra, chương trình của bạn sau đó sẽ thoát ra - đó là những gì bạn muốn, như bạn có thể thấy lý do tại sao nó xảy ra và xử lý nó một cách chính xác.

+2

+1 cho "không làm điều đó" – Aya

+0

tôi đồng ý. nhưng tôi nhận được điều này: Không thành công: Phương thức Patient.update của bạn đã bắt gặp ngoại lệ loại ZeroDivisionError khi nó không có. Bạn không bao giờ nên sử dụng các mệnh đề 'except' trần trong mã của mình. Chỉ bắt được NoChildExceptions. thay vì điều này: bỏ qua thành công ngoại lệ được nâng lên của loại: ZeroDivisionError bỏ qua thành công huy động ngoại trừ loại: NameError bỏ qua thành công huy động ngoại trừ loại: AttributeError bỏ qua thành công huy động ngoại trừ loại: Loại lỗi bỏ qua thành công huy động ngoại trừ loại : ValueError Đã bắt được thành công NoChildException Kiểm tra hoàn thành –

+0

@ IvanVulović Vì vậy, những gì bạn muốn là * chỉ * bắt 'NoChildException's (điều trái ngược với những gì bạn đã hỏi), vì vậy chỉ cần thực hiện' try: ... except NoChildException: ... ', không cần bất cứ điều gì ưa thích. –

2

Tôi muốn cung cấp điều này như là một cải tiến về câu trả lời được chấp nhận.

try: 
    dosomestuff() 
except MySpecialException: 
    ttype, value, traceback = sys.exc_info() 
    raise ttype, value, traceback 
except Exception as e: 
    mse = convert_to_myspecialexception_with_local_context(e, context) 
    raise mse 

Cách tiếp cận này cải tiến dựa trên câu trả lời chấp nhận bằng cách duy trì stacktrace gốc khi MySpecialException bị bắt, vì vậy khi xử lý ngoại lệ cấp cao nhất của bạn ghi lại ngoại lệ bạn sẽ nhận được một traceback trỏ đến nơi ngoại lệ ban đầu đã được ném .

0

Tôi đã tìm thấy ngữ cảnh trong đó bắt tất cả các lỗi nhưng không phải là một điều xấu, cụ thể là kiểm tra đơn vị.

Nếu tôi có một phương pháp:

def my_method(): 
    try: 
     something() 
    except IOError, e: 
     handle_it() 

Sau đó, nó plausibly có thể có một bài kiểm tra đơn vị đó trông giống như:

def test_my_method(): 
    try: 
     my_module.my_method() 
    except IOError, e: 
     print "shouldn't see this error message" 
     assert False 
    except Exception, e: 
     print "some other error message" 
     assert False 
    assert True 

Bởi vì bây giờ bạn đã phát hiện my_method rằng chỉ cần ném một ngoại lệ bất ngờ.