2008-09-24 39 views
25

有時候,我覺得自己在這裏我要執行像這樣幾個連續的命令的情況:當異常只是需要被忽略時通用異常處理「正道」

try: 
    foo(a, b) 
except Exception, e: 
    baz(e) 
try: 
    bar(c, d) 
except Exception, e: 
    baz(e) 
... 

同樣的模式。

這種感覺是多餘的,過多的語法會導致它在讀取代碼時難以遵循。

在C中,我會用宏很容易地解決這類問題,但不幸的是,這不能用直接的python來完成。

問題:在遇到這種模式時,如何最好地減少代碼佔用量並提高代碼可讀性?

回答

62

你可以使用with statement如果你有Python 2.5的

from __future__ import with_statement 
import contextlib 

@contextlib.contextmanager 
def handler(): 
    try: 
     yield 
    except Exception, e: 
     baz(e) 

你比如現在變成:

with handler(): 
    foo(a, b) 
with handler(): 
    bar(c, d) 
4

如果他們是簡單的一個行命令,你可以在lambda S環繞他們:

for cmd in [ 
    (lambda: foo (a, b)), 
    (lambda: bar (c, d)), 
]: 
    try: 
     cmd() 
    except StandardError, e: 
     baz (e) 

你可以換的是整件事的功能,所以它看起來像這樣:

ignore_errors (baz, [ 
    (lambda: foo (a, b)), 
    (lambda: bar (c, d)), 
]) 
3

我發現最好的方法,是定義像這樣的功能:

def handle_exception(function, reaction, *args, **kwargs): 
    try: 
     result = function(*args, **kwargs) 
    except Exception, e: 
     result = reaction(e) 
    return result 

但只是不覺得還是看在實踐中正確的:

handle_exception(foo, baz, a, b) 
handle_exception(bar, baz, c, d) 
+5

你可以通過僅返回而不是分配給「結果」來簡化該功能。 – 2008-09-24 19:06:54

-4

在特定情況下,你可以這樣做:

try: 
    foo(a, b) 
    bar(c, d) 
except Exception, e: 
    baz(e) 

或者,你可以捕捉上述異常一步:

try: 
    foo_bar() # This function can throw at several places 
except Exception, e: 
    baz(e) 
+3

如果foo()引發異常,bar()將不會被執行。這不是理想的行爲。 – Sufian 2008-09-24 19:10:01

3

你可以嘗試這樣的事情。這是含糊的宏觀狀態。

class TryOrBaz(object): 
    def __init__(self, that): 
     self.that= that 
    def __call__(self, *args): 
     try: 
      return self.that(*args) 
     except Exception, e: 
      baz(e) 

TryOrBaz(foo)(a, b) 
TryOrBaz(bar)(c, d) 
+5

你的間距太可怕了。請參閱「表達式和語句中的空格」http://www.python.org/dev/peps/pep-0008/ – jfs 2008-09-25 03:58:50

11

如果這是永遠,總是要在一個特定的功能引發了異常,您可以使用一個裝飾的行爲:

def handle_exception(handler): 
    def decorate(func): 
     def call_function(*args, **kwargs): 
      try: 
       func(*args, **kwargs) 
      except Exception, e: 
       handler(e) 
     return call_function 
    return decorate 

def baz(e): 
    print(e) 

@handle_exception(baz) 
def foo(a, b): 
    return a + b 

@handle_exception(baz) 
def bar(c, d): 
    return c.index(d) 

用法:

>>> foo(1, '2') 
unsupported operand type(s) for +: 'int' and 'str' 
>>> bar('steve', 'cheese') 
substring not found