2015-05-25 1 views
9

У меня есть список функций, которые могут потерпеть неудачу, и если один из них не работает, я не хочу, чтобы сценарий остановился, но для продолжения следующей функции.Как предотвратить «слишком широкое исключение» в этом случае?

Я уверен, выполнение его с чем-то вроде этого:

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()) 

Это работает хорошо, но это не PEP8 соответствует:

При ловле исключения, упоминаются конкретные исключения, когда возможно, вместо того, чтобы использовать голый, кроме: clause.

Например, используйте:

try: 
    import platform_specific_module 
except ImportError: 
    platform_specific_module = None 

Голые за исключением: статьи поймает SystemExit и KeyboardInterrupt исключений, что делает его более трудным, чтобы прервать программу с помощью Control-C, и может скрыть другие проблемы. Если вы хотите поймать все исключения , что ошибки сигнальной программы, используйте исключение Исключение: (голый кроме эквивалент, кроме BaseException:).

Хорошее эмпирическое правило, чтобы ограничить использование голой «за исключением» статей в двух случаях:

Если обработчик исключений будет распечатывания или протоколирование отслеживающий; по крайней мере, пользователь будет знать, что произошла ошибка.

Если код должен выполнять некоторую работу по очистке, но затем разрешает исключение с повышением вверх. попробуйте ... наконец, может быть лучший способ обработки этого случая.

Как это сделать?

+0

Я не понимаю, о чем вы спрашиваете. Какие исключения вы * хотите обрабатывать? – BrenBarn

+1

Какие исключения могут быть вызваны вашей функцией? – haifzhan

+2

'except Exception:' отличается от bare 'except:'. Этот раздел PEP8 предупреждает о последнем, вы делаете первое. – roippi

ответ

13

Руководство по PEP8, которое вы цитируете, предполагает, что в вашем случае можно использовать голые исключения, если вы регистрируете ошибки. Я бы подумал, что вы должны покрыть столько исключений, сколько сможете/знаете, как бороться, а затем регистрировать остальные и pass, например.

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

'except KeyboardInterrupt: raise' здесь абсолютно бесполезен. 'KeyboardInterrupt' никогда не будет схвачен' except Exception', потому что 'KeyboardInterrupt' происходит от' BaseException', а не 'Exception'. – roippi

+0

Просто хотел пример известного исключения, не понимал, что «KeyboardInterrupt» - плохой пример. Я изменил его на какой-то общий «KnownException» ... –

+0

Голый, кроме более подходящего здесь. 'logging.exception()' автоматически записывает ошибку и трассировку. – user2923419

0

Возможно, вы имеете в виду, что каждая функция может вызывать различные исключения? Когда вы указываете тип исключения в предложении except, это может быть любое имя, которое ссылается на исключение, а не только на имя класса.

например.

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__) 

печатает:

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 

Конечно, это оставляет вас, не зная, что делать, когда происходит каждое исключение. Но поскольку вы просто хотите игнорировать его и продолжать, это не проблема.

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

Как это вообще ответит на вопрос? –

+2

Это не объясняет, в чем проблема, и не затрагивает вопрос, а именно, как поймать только нужные исключения. –

0

//youtrack.jetbrains.ком/вопрос/PY-9715

PY-9715 Противоречивые "Слишком широкие положения исключение" инспекции [ "Слишком широкие положения исключений" осмотр] [1]

//legacy.python .org/Dev/Peps/PEP-0348/

BaseException

суперкласса, что все исключения му наследовать. Это имя было , выбранное для отражения того, что оно находится в основе иерархии исключений , будучи самим исключением. «Raisable» считался именем, он был передан, потому что его имя неправильно отражало факт , что это само исключение.

Непосредственное наследование BaseException не ожидается, и будет обескуражен для общего случая. Большинство пользовательских исключений должны наследовать вместо Exception. Это позволяет перехватить исключение , продолжая работать в общем случае, чтобы поймать все исключения, которые должны быть пойманы . Прямое наследование BaseException должно быть только сделано в случаях, когда требуется совершенно новая категория исключения.

Но для случаев, когда все исключения должны быть вслепую, кроме BaseException будет работать.

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

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

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

Смежные вопросы