【问题标题】:Get URL when handling urllib2.URLError处理 urllib2.URLError 时获取 URL
【发布时间】:2011-06-28 15:53:18
【问题描述】:

这与 urllib2 相关,但更普遍的是自定义异常处理。如何通过引发的异常将附加信息传递给另一个模块中的调用函数?我假设我会使用自定义异常类重新引发,但我不确定技术细节。

我不会用我尝试过但失败过的东西来污染示例代码,而是将它简单地呈现为一个几乎是空白的石板。我的最终目标是让示例中的最后一行起作用。

#mymod.py
import urllib2

def openurl():
    req = urllib2.Request("http://duznotexist.com/")
    response = urllib2.urlopen(req)

#main.py
import urllib2
import mymod

try:
    mymod.openurl()
except urllib2.URLError as e:
    #how do I do this?
    print "Website (%s) could not be reached due to %s" % (e.url, e.reason)

【问题讨论】:

    标签: python exception-handling urllib2


    【解决方案1】:

    您可以添加信息,然后重新引发异常。

    #mymod.py
    import urllib2
    
    def openurl():
        req = urllib2.Request("http://duznotexist.com/")
        try:
            response = urllib2.urlopen(req)
        except urllib2.URLError as e:
            # add URL and reason to the exception object
            e.url = "http://duznotexist.com/"
            e.reason = "URL does not exist"
            raise e # re-raise the exception, so the calling function can catch it
    
    #main.py
    import urllib2
    import mymod
    
    try:
        mymod.openurl()
    except urllib2.URLError as e:
        print "Website (%s) could not be reached due to %s" % (e.url, e.reason)
    

    【讨论】:

    • +1 是的,这就是我想要的。我认为这很简单,但我只是没有通过谷歌或反复试验到达那里。
    • urlib2.urlopen() 将跟随重定向 - 所以e.url_original 会更合适。我无法弄清楚如何获取触发 URLError 的url_actual。我不是在这里挑剔。如果您正在打开 a.com ,并且它 301 重定向到 b.com , urlopen 将自动跟随它,因为引发了带有重定向的 HTTPError 。如果 b.com 导致 URLError ,上面的代码将 a.com 标记为不存在 - 当它正常工作时,它只是指向 b.com 的错误 url。
    • e.reason = "URL does not exist" 将提供AttributeError: can't set attribute
    【解决方案2】:

    我不认为重新引发异常是解决此问题的合适方法。

    正如@Jonathan Vanasco 所说,

    如果您正在打开 a.com ,并且它 301 重定向到 b.com , urlopen 将自动跟随它,因为引发了带有重定向的 HTTPError 。如果 b.com 导致 URLError ,上面的代码将 a.com 标记为不存在

    我的解决方案是覆盖redirect_request of urllib2.HTTPRedirectHandler

    import urllib2
    
    class NewHTTPRedirectHandler(urllib2.HTTPRedirectHandler):
        def redirect_request(self, req, fp, code, msg, headers, newurl):
            m = req.get_method()
            if (code in (301, 302, 303, 307) and m in ("GET", "HEAD")
                or code in (301, 302, 303) and m == "POST"):
                newurl = newurl.replace(' ', '%20')
                newheaders = dict((k,v) for k,v in req.headers.items()
                                  if k.lower() not in ("content-length", "content-type")
                                 )
                # reuse the req object
                # mind that req will be changed if redirection happends
                req.__init__(newurl,
                    headers=newheaders,
                       origin_req_host=req.get_origin_req_host(),
                       unverifiable=True)
                return req
            else:
                raise HTTPError(req.get_full_url(), code, msg, headers, fp)
    
    opener = urllib2.build_opener(NewHTTPRedirectHandler)
    urllib2.install_opener(opener)
    # mind that req will be changed if redirection happends
    #req = urllib2.Request('http://127.0.0.1:5000')
    req = urllib2.Request('http://www.google.com/')
    
    try:
        response = urllib2.urlopen(req)
    except urllib2.URLError as e:
        print 'error'
        print req.get_full_url()
    else:
        print 'normal'
        print response.geturl()
    

    让我们尝试将 url 重定向到一个未知的 url:

    import os
    from flask import Flask,redirect
    
    app = Flask(__name__)
    
    @app.route('/')
    def hello():
        # return 'hello world'
        return redirect("http://a.com", code=302)
    
        if __name__ == '__main__':
        port = int(os.environ.get('PORT', 5000))
        app.run(host='0.0.0.0', port=port)
    

    结果是:

    error
    http://a.com/
    
    normal
    http://www.google.com/
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-26
      • 2012-08-09
      • 2013-11-18
      • 1970-01-01
      • 1970-01-01
      • 2018-01-26
      相关资源
      最近更新 更多