2012-02-21 51 views
11

Tôi đã tạo ra một loạt các hàm và tôi cần rất giống ngoại trừ các mệnh đề trong tất cả chúng, nhưng tôi ghét có quá nhiều dòng thử và ngoại trừ các mệnh đề và cùng mã bên trong mỗi hàm. Ví dụ:Lặp đi lặp lại thử và trừ các khoản

import sys 
import random 

def foo(): 
    num=random.random() 
    try: 
     if num>0.5: print 'OK' 
     elif num>0.25: raise NameError('Too Small') 
     else: raise KeyboardInterrupt 
    except NameError: 
     print "%s had a NameError" % sys._getframe().f_code.co_name 
    except: 
     print "%s had a different Error" % sys._getframe().f_code.co_name 

def bar(): 
    num=random.random() 
    try: 
     if num>0.8: print 'OK' 
     elif num>0.6: raise NameError('Too Small') 
     else: raise KeyboardInterrupt 
    except NameError: 
     print "%s had a NameError" % sys._getframe().f_code.co_name 
    except: 
     print "%s had a different Error" % sys._getframe().f_code.co_name 

Mã sau "thử" khác với chức năng, nhưng mã sau "ngoại trừ" giống nhau. Tôi muốn hợp nhất những câu ngoại trừ để họ không làm cho mã của tôi trông rất chật chội. Có cách nào tốt để làm điều này?

+1

Bắt bất kỳ ngoại lệ nào thường là một ý tưởng tồi. Nó che dấu các vấn đề thực sự và làm cho việc gỡ lỗi trở nên khó khăn hơn. Nắm bắt bất kỳ ngoại lệ nào bạn biết - nếu bạn không biết về chúng, bạn có thực sự muốn bắt chúng không? –

+0

Đó là một điểm tốt. Nếu chức năng không thành công, tôi cần kịch bản để tiếp tục. "Ngoại trừ" cuối cùng bao gồm 'print sys.exc_info() [: 2]' bao gồm tên của ngoại lệ. Có cách nào tốt hơn để làm điều này? – crunkchitis

Trả lời

22

Python Decorators là những gì bạn muốn.

Bạn cho biết khối ngoại lệ luôn giống nhau. Thực hiện một trang trí tùy chỉnh mà làm những gì bạn muốn. Bạn sẽ phải áp dụng điều này cho mỗi chức năng/phương pháp nhưng nó chắc chắn không lưu trùng lặp.

def handleError(function): 
    def handleProblems(): 
     try: 
      function() 
     except Exception: 
      print "Oh noes" 
    return handleProblems 


@handleError 
def example(): 
    raise Exception("Boom!") 

Khi gọi một phương thức với các trang trí áp dụng:

 
>>> 
>>> example() 
Oh noes 
>>> 

Bạn sẽ cần phải thay đổi các loại ngoại lệ cũng như những gì bạn làm, nhưng bạn sẽ có được jist của nơi tôi sẽ có điều này.

+0

tuyệt vời. cám ơn vì cái này. – crunkchitis

+0

@crunkchitis bạn được chào đón. – Finglas

+2

Đây không phải là một ví dụ tốt bởi vì trình trang trí sẽ không hoạt động đối với các hàm có tham số. – user3467349

6

Nội dung bên trong khối try của bạn là nội dung thú vị, do đó phải có chức năng. Sau đó, chỉ cần chọn chức năng bạn muốn, và gọi nó, được bao bọc bởi các ngoại lệ của bạn. Bạn thậm chí có thể viết mã ngoại lệ như một hàm, và chuyển hàm đã chọn cho hàm này làm đối số. ví dụ.

def foo(): 
    num=random.random() 
    if num>0.5: print 'OK' 
    elif num>0.25: raise NameError('Too Small') 
    else: raise KeyboardInterrupt 

def bar(): 
    num=random.random() 
    if num>0.8: print 'OK' 
    elif num>0.6: raise NameError('Too Small') 
    else: raise KeyboardInterrupt 

def try_numerics(f): 
    try: 
     f() 
    except NameError: 
     print "%s had a NameError" % sys._getframe().f_code.co_name 
    except: 
     print "%s had a different Error" % sys._getframe().f_code.co_name 

# In your main code... 
if (need_to_run_foo): 
    try_numerics(foo) 
elif (need_to_run_bar): 
    try_numerics(bar) 
2

Nếu đó là những chức năng thực tế của bạn, bạn sẽ dễ dàng khái quát hóa chúng.

Bạn có thể tạo một chức năng chung

def general(bottom_num, top_num): 
    num=random.random() 
    try: 
    if num>top_num: print 'OK' 
    elif num>bottom_num: raise NameError('Too Small') 
    else: raise KeyboardInterrupt 
    except NameError: 
    print "%s had a NameError" % sys._getframe().f_code.co_name 
    except: 
    print "%s had a different Error" % sys._getframe().f_code.co_name 

này sẽ giữ mã của bạn từ lặp đi lặp lại và giải quyết các thử: trừ: Vấn đề

5

Câu trả lời trên không áp dụng cho các chức năng mà một vài tham số - cho trường hợp sau, tôi nghĩ rằng bạn sẽ muốn một cái gì đó như thế này:

def handleError(f): 
    def handleProblems(*args, **kwargs): 
     try: 
      return f(*args, **kwargs) 
     except Exception: 
      print "Oh noes" 
    return handleProblems 

Chúng ta có thể kiểm tra nó như vậy:

@handleError 
def addTwo(x, y): 
    print(x + y) 

>>> addTwo(5,5) 
10 
>>> addTwo(5, 's') 
Oh noes 
0

Tôi đã chạy vào cùng một trường hợp gần đây, trong trường hợp của tôi, tôi có một số ngoại lệ tùy chỉnh dựa trên đó tôi cần đăng nhập hoặc tăng ngoại lệ thêm. Tôi đã tạo một phương thức trang trí để xử lý các ngoại lệ theo loại.

try: 
    obj.some_method() 
except Exception as e: 
    catch_and_log_exception(e) 


def catch_and_log_exception(e): 
    if isinstance(e, MyConnectionError): 
     print "Connection error : %s." % e.message 
     sys.exit(1) 
    elif isinstance(e, MyConnectionTimeout): 
     print "Connection to server has been timed out. %s" % e.message 
     sys.exit(1) 
    elif isinstance(e, MyException): 
     message = e.explanation if e.explanation else e.message 
     log_error_message(str(message)) 
     print "Failed, please check the logs." 
     sys.exit(1) 
    else: 
     raise e 

Hy vọng trợ giúp này !!

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