2015-05-25 7 views
9

Ich habe eine Liste von Funktionen, die möglicherweise fehlschlagen, und wenn eine fehlschlägt, möchte ich nicht das Skript zu stoppen, sondern mit der nächsten Funktion fortfahren.Wie kann man in diesem Fall eine "zu breite Ausnahme" verhindern?

Ich Ausführung es mit etwas wie folgt aus:

list_of_functions = [f_a,f_b,f_c] 
for current_function in list_of_functions: 
    try: 
     current_function() 
    except Exception: 
     print(traceback.format_exc()) 

Es funktioniert gut, aber es ist nicht PEP8 konform:

Wenn Ausnahmen fangen, erwähnen bestimmte Ausnahmen, wenn möglich anstelle der Verwendung eine bloße Ausnahme: Klausel.

Zum Beispiel verwenden:

try: 
    import platform_specific_module 
except ImportError: 
    platform_specific_module = None 

Ein nackte Ausnahme: Klausel Systemexit und KeyboardInterrupt Ausnahmen abfangen, so dass es schwieriger, ein Programm mit Strg-C zu unterbrechen, und andere Probleme verschleiern kann. Wenn Sie alle Ausnahmen abfangen wollen, die Programmfehler signalisieren, verwenden Sie außer Ausnahme: (blank außer entspricht außer BaseException:).

Eine gute Daumenregel ist die Verwendung von bloßen ‚mit Ausnahme von‘ Klauseln zwei Fälle zu beschränken:

Wenn der Ausnahmebehandler der Zurückverfolgungs seines Ausdrucken oder Anmeldung; zumindest wird dem Benutzer bekannt sein, dass ein Fehler aufgetreten ist.

Wenn der Code einige Aufräumarbeiten durchführen muss, lässt er die Ausnahme jedoch mit Raise nach oben propagieren. versuchen Sie ... schließlich kann eine bessere Weise sein, diesen Fall zu behandeln.

Wie ist dies der gute Weg?

+0

Ich verstehe nicht, was du verlangst. Welche Arten von Ausnahmen wollen * Sie * handhaben? – BrenBarn

+1

Welche Ausnahmen könnten von Ihrer Funktion ausgelöst werden? – haifzhan

+2

'except Ausnahme:' ist anders als blank 'außer: '. Dieser Abschnitt von PEP8 warnt vor letzterem, Sie machen das erstere. – roippi

Antwort

13

Der von Ihnen angegebene PEP8-Leitfaden schlägt vor, dass es in Ihrem Fall zulässig ist, eine bloße Ausnahme zu verwenden, vorausgesetzt, Sie protokollieren die Fehler. Ich würde denken, dass Sie so viele Ausnahmen abdecken sollten, wie Sie können/wissen, wie man damit umgeht und dann den Rest notiert und pass, z.

import logging 

list_of_functions = [f_a,f_b,f_c] 
for current_function in list_of_functions: 
    try: 
     current_function() 
    except KnownException: 
     raise 
    except Exception as e: 
     logging.exception(e) 
+0

'außer KeyboardInterrupt: Raise 'ist hier nicht notwendig. 'KeyboardInterrupt' wird niemals von' except Exception' abgefangen, da 'KeyboardInterrupt' von' BaseException' und nicht von 'Exception' abgeleitet ist. – roippi

+0

Wollte nur ein Beispiel für eine bekannte Ausnahme, nicht realisiert "KeyboardInterrupt" ist ein schlechtes Beispiel. Ich habe es in eine generische 'KnownException' geändert ... –

+0

Ein blankes ist hier besser geeignet. 'logging.exception()' zeichnet den Fehler und das Traceback automatisch auf. – user2923419

0

Meinst du vielleicht, dass jede Funktion verschiedene Ausnahmen auslösen kann? Wenn Sie den Ausnahmetyp in der Klausel "except" benennen, kann es sich um einen beliebigen Namen handeln, der auf eine Ausnahme verweist, nicht nur auf den Klassennamen.

z.

def raise_value_error(): 
    raise ValueError 

def raise_type_error(): 
    raise TypeError 

def raise_index_error(): 
    doesnt_exist 

func_and_exceptions = [(raise_value_error, ValueError), (raise_type_error, TypeError), 
    (raise_index_error, IndexError)] 

for function, possible_exception in func_and_exceptions: 
    try: 
     function() 
    except possible_exception as e: 
     print("caught", repr(e), "when calling", function.__name__) 

druckt:

caught ValueError() when calling raise_value_error 
caught TypeError() when calling raise_type_error 
Traceback (most recent call last): 
    File "run.py", line 14, in <module> 
    function() 
    File "run.py", line 8, in raise_index_error 
    doesnt_exist 
NameError: name 'doesnt_exist' is not defined 

Natürlich, die Sie nicht wissen, was tun lässt, wenn jede Ausnahme auftritt. Aber da du es einfach ignorieren und weitermachen willst, ist das kein Problem.

1
__author__ = 'xray' 
# coding: utf8 
from wiki_baike import url_manager, html_downloader, html_parser, html_outputer 
import logging 

class SpiderMain(object): 
    def __init__(self): 
     self.url = url_manager.UrlManager() 
     self.downloader = html_downloader.HtmlDownloader() 
     self.parser = html_parser.HtmlParser() 
     self.outputer = html_outputer.HtmlOutputer() 

    def craw(self, root_url): 
     count = 1 
     self.urls.add_new_url(root_url) 
     while self.urls.has_new_url(): 
      try: 
       new_url = self.urls.get_new_url() 
       print 'craw %d : %s' % (count, new_url) 
       html_cont = self.downloader.download(new_url) 
       new_urls, new_data = self.parser.parse(new_url, html_cont) 
       self.urls.add_new_urls(new_urls) 
       self.outputer.collect_data(new_data) 
       if count == 1000: 
        break 
       count += 1 
      except Exception as e: 
       logging.exception(e) 
       print 'error' 
     self.outputer.output_html() 

    if __name__=='__main__': 
    root_url = 'http://baike.baidu.com/view/21087.html' 
    # root_url = 'https://rollbar.com/docs/' 
    obj_spider = SpiderMain() 
    obj_spider.craw(root_url) 
+1

Wie beantwortet das die Frage überhaupt? –

+2

Es erklärt nicht, was das Problem ist, und behandelt nicht die Frage, nämlich wie man nur die gewünschten Ausnahmen fängt. –

0

//youtrack.jetbrains.com/Ausgabe/PY-9715

PY-9715 Uneinheitliche "Zu breit Ausnahmeklauseln" Inspektion [ "Zu breit Ausnahmeklauseln" Inspektion] [1]

//legacy.python .org/dev/pep/pep-0348/

BaseException

Die übergeordnete Klasse, dass alle Ausnahmen mu st erbt von. Sein Name wurde gewählt, um zu reflektieren, dass es an der Basis der Ausnahmehierarchie ist , während eine Ausnahme selbst ist. "Raisable" wurde als Name betrachtet, es wurde weitergegeben, weil sein Name die Tatsache nicht richtig widerspiegelte, dass es eine Ausnahme selbst ist.

Direkte Vererbung von BaseException wird nicht erwartet und wird für den allgemeinen Fall abgeraten werden. Die meisten benutzerdefinierten Ausnahmen sollten stattdessen von Exception erben. Dies ermöglicht das Abfangen von Exception auf weiterhin im üblichen Fall des Abfangen aller Ausnahmen, die sollte gefangen werden. Die direkte Vererbung von BaseException sollte nur erfolgen, wenn eine völlig neue Kategorie von Ausnahmen gewünscht wird.

Aber für Fälle, in denen alle Ausnahmen blind gefangen werden sollten, außer BaseException wird funktionieren.

[1] http://i.stack.imgur.com/8UByz.png

//youtrack.jetbrains.com/issue/PY-9715

//legacy.python.org/dev/peps/pep-0348/

Verwandte Themen