2015-12-26 9 views
6

Sagen, ich habe die folgenden vier Variablen Handhabung:Ausnahmen separat in Pythons gleiche Typs

>>> f1 = (print, 1, 2 ,3 ,4) 
>>> f2 = (exit, 1, 2 ,3 ,4) 
>>> f3 = (1, 2, 3, 4) 
>>> f4 = 4 

In einem hypothetischen Programm erwarte ich, dass jeder dieser Variablen ein Tupel halten, erstes Element, das sollte der Name sein, Funktion, und deren nachfolgende Elemente sollten die Funktion Parameter in der Reihenfolge sein.

ich eine Funktion auf diese Weise wie so gespeichert nennen könnte:

>>> f1[0](*f1[1:]) 
1 2 3 4 

Allerdings sind die meisten dieser Variablen sind nicht im ausgenommen Format, und ich möchte die Berufung von ihnen in der Lage sein innen zu kapseln try/except Blöcke, um diese Situationen zu behandeln.

Nun, obwohl die Funktionsaufrufe von f2, f3 und f4 Pause radikal anderen Grund, sie alle die gleiche Art von Ausnahme auslösen, ein TypeError:

>>> f2[0](*f2[1:]) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: __call__() takes from 1 to 2 positional arguments but 5 were given 
>>> f3[0](*f3[1:]) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: 'int' object is not callable 
>>> f4[0](*f4[1:]) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: 'int' object is not subscriptable 

Damit ein generisches Tun:

try: 
    f[0](*f[1:]) 
except TypeError: 
    # handle exception 

Würde mir nicht genügend Informationen zur Verfügung stellen, um jede Ausnahme entsprechend zu behandeln.

Was wäre der richtige Weg, um zwischen verschiedenen Ausnahmen desselben Typs in Python zu unterscheiden?

Antwort

2

So müssen Sie eine andere Methode des Aufrufs als function(*tuple) verwenden. Hier ist ein Beispiel für eine Funktion fun_apply, die eine bestimmte Funktion mit Positions- und Schlüsselwortargumenten aufruft. Es fügt eine explizite Überprüfung hinzu, um sicherzustellen, dass args iterierbar ist und kwargs von collection.Mapping erbt.

from collections import Mapping 

def fun_apply(f, args=None, kwargs=None):                     
    if args is None: 
     args = [] 
    if kwargs is None: 
     kwargs = {} 

    try: 
     args = iter(args) 
    except TypeError: 
     # handle args being non-iterable 
     pass 

    if isinstance(kwargs, collections.Mapping): 
     pass 
    else: 
     # handle kwargs being a non-mapping 
     pass 

    if hasattr(f, '__call__'): 
     pass 
    else: 
     # handle f being non-callable 
     pass 

    try: 
     f(*args, **kwargs) 
    except TypeError as e: 
     raise TypeError(e) 

Die andere Option ist die message Zeichenfolge explizit zu verarbeiten, aber die unbeabsichtigte Folge und die Fehlermeldungen haben könnte, sich zwischen den Versionen von Python unterscheiden könnte.

+0

Ich verstehe diese Ansätze funktionieren in Fällen, in denen ich 'TypeError' (oder eine Unterklasse davon) manuell auslösen. Wie würden sie sich auf Situationen beziehen, in denen die Ausnahme ohne meine direkte Eingabe ausgelöst wird, wie in meinen Beispielfunktionen? – zayora

+0

Richtig, wenn Sie die falsche Anzahl von Argumenten oder unerwartete Schlüsselwortargumente eingeben, werden Sie einen 'TypeError' auslösen und der Körper Ihrer Funktion wird nicht ausgewertet. Wenn Sie jedoch etwas wie 'fun_apply' verwenden, können Sie diesen' TypeError' abfangen und eine neue Ausnahme, 'TypeError' oder andere, auslösen, die die aufgerufene Funktion umschließt. –

+0

Aber was, wenn das nicht ist, was ich in allen Fällen mit meinem 'try' /' except'-Block machen möchte? Was ist, wenn ich nur den Fall abfangen möchte, in dem eine ordnungsgemäße Funktion (oder aufrufbar) wie 'exit' mit zu vielen (oder zu wenigen) Parametern aufgerufen wird und eine Warnung ausgegeben werden soll, wenn dies geschieht, aber mein Programm immer noch möchte? abstürzen und brennen, wenn das erste Element des Tupel nicht aufrufbar ist (oder die Variable kein Tupel ist)? Wie soll ich das machen? Gibt es zusätzliche Informationen, die ich aus dem Ausnahmeobjekt sammeln kann, die es mir erlauben würden, mit diesen Situationen richtig umzugehen? – zayora