Immagino che una soluzione potrebbe essere solo imprecisa a causa della mancanza di regole di digitazione statiche.
Non sono a conoscenza di uno strumento che controlla le eccezioni, ma potresti trovare uno strumento personalizzato che corrisponda alle tue esigenze (una buona possibilità per giocare un po 'con l'analisi statica).
Come primo tentativo, potresti scrivere una funzione che costruisce un AST, trova tutto Raise
nodi e quindi cerca di capire modelli comuni di generazione di eccezioni (ad esempio chiamando direttamente un costruttore)
Sia x
il seguente programma:
x = '''\
if f(x):
raise IOError(errno.ENOENT, 'not found')
else:
e = g(x)
raise e
'''
Costruisci l'AST utilizzando il compiler
pacchetto:
tree = compiler.parse(x)
Quindi definisci una Raise
classe visitatore:
class RaiseVisitor(object):
def __init__(self):
self.nodes = []
def visitRaise(self, n):
self.nodes.append(n)
E percorri i Raise
nodi di raccolta AST :
v = RaiseVisitor()
compiler.walk(tree, v)
>>> print v.nodes
[
Raise(
CallFunc(
Name('IOError'),
[Getattr(Name('errno'), 'ENOENT'), Const('not found')],
None, None),
None, None),
Raise(Name('e'), None, None),
]
Puoi continuare risolvendo i simboli usando le tabelle dei simboli del compilatore, analizzando le dipendenze dei dati, ecc. Oppure puoi semplicemente dedurre che CallFunc(Name('IOError'), ...)
"dovrebbe sicuramente significare aumentare IOError
", il che è abbastanza OK per risultati pratici rapidi :)
raise
stringhe, non soloBaseException
sottoclassi. Quindi, se stai chiamando il codice della libreria che è fuori dal tuo controllo, ancheexcept Exception
se non è sufficiente, poiché non cattura eccezioni di stringa. Come altri hanno sottolineato, qui stai abbaiando contro l'albero sbagliato.