【问题标题】:Identify a specific exception in python识别python中的特定异常
【发布时间】:2015-09-16 07:13:57
【问题描述】:

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

我正在编写一个抓取器,它可以抓取许多不同的网站,以及一些我想处理的错误,而一些我只想忽略。

我除了这样的例外:

except Exception as e:

我可以这样识别的大多数异常:

type(e).__name__ == "IOError"

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

它的名称“错误”太模糊了,我猜其他错误也有这个名称。我猜我可以以某种方式从我的异常中获取 errno 编号,从而识别它。但我不知道怎么做。

【问题讨论】:

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


    【解决方案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”except 子句,该子句将记录错误和回溯某处以免丢失(logging.exception 是您的朋友),清理必须清理的内容并以更友好的错误消息终止。

    很少有人真的想忽略一个异常(我的意思是假装没有发生任何错误或意外并愉快地继续)。至少您将希望通知用户其中一个操作失败以及原因 - 在您的情况下,这可能是一个顶级循环迭代一组要废弃的站点,内部尝试/除块捕获“预期”错误情况,即:

    # 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 模块需要一些时间来学习,但从长远来看它确实有回报。

    【讨论】:

    • 发生异常时,我有两种情况,要么我想忽略它,要么我想给自己发送一封包含所有信息(stacktrace 等)的电子邮件,并且我有很多我忽略的异常:IOerrors , timeout, UrlError, HtttpError,SSLerror, Timeoutexception 我想将此异常添加到该列表中。我的程序基本上是一个循环,每 5 分钟抓取大约 15 个网页,上面的错误我只想忽略(例如,一个页面可能已关闭),但其他我想收到通知
    猜你喜欢
    • 1970-01-01
    • 2021-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-16
    • 1970-01-01
    • 2012-11-11
    • 2021-10-28
    相关资源
    最近更新 更多