在python中识别特定的异常

时间:2015-09-16 07:13:57

标签: python exception error-handling exception-handling web-scraping

我在识别异常时遇到问题。

我正在写一个刮擦很多不同网站的刮刀,还有一些我想要处理的错误,有些我只想忽略。

我除了我这样的例外:

except Exception as e:

我可以识别的大部分例外情况如下:

type(e).__name__ == "IOError"

但我有一个例外“[Errno 10054]现有连接被远程主机强行关闭”

其名称为“error”太模糊了,我猜其他错误也有这个名字。我猜我可以以某种方式从我的异常中获取errno数字,从而识别它。但我不知道如何。

1 个答案:

答案 0 :(得分:1)

首先,您不应该依赖异常的类名,但是在类本身上 - 来自两个不同模块的两个类可以具有__name__属性的相同值,同时具有不同的异常。所以你想要的是:

try:
    something_that_may_raise()
except IOError as e:
     handle_io_error(e)
except SomeOtherError as e:
     handle_some_other_error(e)

等...

然后你有两种例外:你可以用这种或那种方式处理的那种,以及其他的例外。如果该程序仅供您个人使用,则最好的方法是处理"其他的"通常根本不处理它们 - Python运行时将捕获它们,显示包含所有相关信息的良好回溯(因此您知道发生了什么以及在哪里并最终可以为此情况添加一些处理)。

如果它是"公共"程序和/或如果在程序崩溃之前确实有一些要清理的东西,你可以添加最后一个" catch all"除了程序顶级的条款,它会在某处记录错误和追溯,因此它不会丢失(logging.exception是你的朋友),清理必须清理的内容并以更友好的方式终止错误信息。

极少数情况下,人们真的想要忽略异常(我的意思是假装没有错误或意外发生并愉快地继续)。至少你会想要通知用户其中一个操作失败以及为什么 - 在你的情况下可能是一个顶级循环迭代一组站点要废弃,内部try / except阻止捕获&#34 ;预期"错误情况,即:

# config: 
config = [
   # ('url', {params})
   ('some.site.tld', {"param1" : value1, "param2" : value2}),
   ('some.other.tld', {"param1" : value1, "answer" : 42}),
   # etc
   ]

def run():
    for url, params in config:
        try:
            results = scrap(url, **params)

        except (SomeKnownError, SomeOtherExceptedException) as e:
            # things that are to be expected and mostly harmless
            #
            # you configured your logger so that warnings only
            # go to stderr
            logger.warning("failed to scrap %s : %s - skipping", url, e)
        except (MoreSeriousError, SomethingIWannaKnowAbout) as e:
            # things that are more annoying and you want to know
            # about but that shouldn't prevent from continuing 
            # with the remaining sites
            #
            # you configured your logger so that exceptions goes
            # to both stderr and your email.
            logger.exception("failed to scrap %s : %s - skipping", url, e)
        else:
            do_something_with(results)

然后在run()调用周围有一个处理意外错误的顶级处理程序:

def main(argv):
    parse_args() 
    try:
        set_up_everything()
        run()
        return 0
    except Exception as e:
        logger.exception("oops, something unexpected happened : %s", e)
        return 1
    finally:
        do_some_cleanup()

if __name__ == "__main__":
    sys.exit(main(sys.argv))

请注意logging module has an SMTPHandler - 但由于邮件也很容易失败,您最好还是在本地更好地拥有可靠的日志(stderr和tee到文件?)。 logging模块需要一些时间来学习,但从长远来看它确实是值得的。