代码之家  ›  专栏  ›  技术社区  ›  alvas

使用urllib、urllib2和request避免类似于“末日金字塔”的语法

  •  2
  • alvas  · 技术社区  · 7 年前

    很难写出Python2和Python3 request 响应的依赖项代码,因为它们 urlopen() 功能和 requests.get() 函数返回不同类型:

    • 蟒蛇2 urllib.request.urlopen() 返回a http.client.HTTPResponse
    • 蟒蛇3 urllib.urlopen(url) 返回 instance
    • 要求 request.get(url) 返回a requests.models.Response

    支持Python2和Python3以及不想安装 要求 依赖,我试过一个“末日金字塔”的样子 try-except 在导入和 get_content() 功能:

    try: # Try importing requests first.
        import requests
    except ImportError: 
        try: # Try importing Python3 urllib
            import urllib.request
        except AttributeError: # Now importing Python2 urllib
            import urllib
    
    
    def get_content(url):
        try:  # Using requests.
            return requests.get(url).content # Returns requests.models.Response.
        except NameError:  
            try: # Using Python3 urllib.
                with urllib.request.urlopen(index_url) as response:
                    return response.read() # Returns http.client.HTTPResponse.
            except AttributeError: # Using Python3 urllib.
                return urllib.urlopen(url).read() # Returns an instance.
    

    是否有其他方法可以达到返回读取内容和避免嵌套 尝试例外 ?

    3 回复  |  直到 7 年前
        1
  •  7
  •   mhawke    7 年前

    您的用户使用 requests ? 更容易忽视 并支持标准库功能。这可以通过如下方式导入,对其余代码透明:

    try:
        from urllib.request import urlopen
    except ImportError:
        from urllib2 import urlopen
    

    从那时起,所有GET请求都可以使用 urlopen(url) . 返回的数据可以使用 read() .

    现在,如果你真的想继续 请求 支持,您可以编写导入代码以及 get_content() 这样地:

    try:
        import requests
        get_content = lambda url : requests.get(url).content
    except ImportError:
        try:                   # Python 3
            from urllib.request import urlopen
        except ImportError:    # Python2
            from urllib2 import urlopen
        get_content = lambda url : urlopen(url).read()
    
        2
  •  1
  •   Tarun Lalwani    7 年前

    正如每个人都提到的,如果您选择urllib的路线,那么您不应该为请求操心太多。但是,如果您仍然想避开太多的嵌套异常,可以使用下面的方法

    import sys
    key = str(sys.version_info.major)
    
    try:  # Try importing requests first.
        import requests
        key = "requests"
    except ImportError:
        try:  # Try importing Python3 urllib
            import urllib.request
        except (AttributeError, ImportError):  # Now importing Python2 urllib
            import urllib
    
    FUNC = {
        "2": {
            "urlopen": lambda url: urllib.urlopen(url),
            "read": lambda res: res.read()
        },
        "requests": {
            "urlopen": lambda url: requests.get(url),
            "read": lambda res: res.content
        },
        "3": {
            "urlopen": lambda url: urllib.request.urlopen(url),
            "read": lambda res: res.read()
        },
    }
    
    urlopen = FUNC[key]["urlopen"]
    read = FUNC[key]["read"]
    
    def get_content(url):
        res = urlopen(url)
        return read(res)
    
    print(get_content("http://tarunlalwani.com"))
    
        3
  •  0
  •   t.m.adam    7 年前

    您可以尝试将所有三个库作为 request ,并检查 get_content 函数来标识导入的库。
    作为嵌套try-except块的替代方法,可以导入 requests 在单独的try except block中, 这样它就会覆盖 urllib / urllib2 ,如果安装了模块。

    try: 
        import urllib.request as request
    except ImportError: 
        import urllib2 as request
    try: 
        import requests as request
    except ImportError:
        pass
    
    def get_content(url):
        return request.get(url).content if hasattr(request, 'get') else request.urlopen(url).read()
    

    这将生成干净的sipmle代码,并允许您处理更复杂的请求,例如,

    def get_content(url, headers={}):
        if hasattr(request, 'get'):
            return request.get(url, headers=headers).content
        else:
            return request.urlopen(request.Request(url, headers=headers)).read()