2008-09-24 6 views
25

कभी कभी मैं स्थिति है जहाँ मैं ऐसे जैसे कई अनुक्रमिक आदेश पर अमल करना चाहते हैं में अपने आप को लगता है:अजगर में जेनेरिक एक्सेप्शन हैंडलिंग "ठीक तरीका"

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

यह एक ही पैटर्न तब होता है जब अपवाद बस अनदेखा किया की जरूरत है।

यह अनावश्यक लगता है और अत्यधिक वाक्यविन्यास कोड पढ़ने के दौरान आश्चर्यजनक रूप से कठिन होने का कारण बनता है।

सी में, मैं इस प्रकार की समस्या को मैक्रो के साथ आसानी से हल कर दूंगा, लेकिन दुर्भाग्यवश, यह सीधे पायथन में नहीं किया जा सकता है।

प्रश्न: मैं इस पैटर्न में आने पर कोड पदचिह्न को कैसे कम कर सकता हूं और कोड पठनीयता को कैसे बढ़ा सकता हूं?

उत्तर

62

आप with statement इस्तेमाल कर सकते हैं अगर आप अजगर है 2.5

from __future__ import with_statement 
import contextlib 

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

आपका उदाहरण अब हो जाता है:

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

वे सरल एक लाइन आदेश हैं, तो आप lambda रों में उन्हें लपेट कर सकते हैं:

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

आप कर सकते हैं उस परिणाम को "परिणाम" को निर्दिष्ट करने के बजाय बस लौटकर सरल बनाएं। –

-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() ने अपवाद उठाया है, तो बार() निष्पादित नहीं किया जाएगा। यह वांछित व्यवहार नहीं है। – Sufian

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

+5

"भयानक" नहीं। बेवकूफ और अटूट। और पास्कल और सी से शुरू होने वाली 30 साल की आदत जल्द ही() के स्थान से रिक्त स्थान को हटाने के लिए किसी भी समय बदल नहीं रही है।उम्र बढ़ने के बुनियादी ढांचे (आंखों, ज्यादातर) के लिए रिक्त स्थान की आवश्यकता है –

+1

आदतें जो हम पठनीय पाते हैं उसे निर्देशित करते हैं। अन्य पुरानी आंखें अन्य आदतों के कारण रिक्त स्थान को विचलित करती हैं। – Alfe

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