Python 避免",;“末日金字塔”;与urllib、urllib2和request的语法类似

Python 避免",;“末日金字塔”;与urllib、urllib2和request的语法类似,python,request,urllib,try-except,Python,Request,Urllib,Try Except,很难为响应编写Python2和Python3以及request依赖项代码,因为它们urlopen()函数和请求。get()函数返回不同的类型: Python2urllib.request.urlopen()返回一个http.client.HTTPResponse Python3urllib.urlopen(url)返回一个实例 RequestRequest.get(url)返回一个requests.models.Response 为了支持Python2和Python3以及不想安装请求依赖项的

很难为响应编写Python2和Python3以及
request
依赖项代码,因为它们
urlopen()
函数和
请求。get()
函数返回不同的类型:

  • Python2
    urllib.request.urlopen()
    返回一个
    http.client.HTTPResponse
  • Python3
    urllib.urlopen(url)
    返回一个
    实例
  • Request
    Request.get(url)
    返回一个
    requests.models.Response
为了支持Python2和Python3以及不想安装
请求
依赖项的用户,我在导入和
get_content()函数中尝试了一个看起来像
try except
的“末日金字塔”:

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.

是否有其他方法可以达到返回读取内容和避免嵌套的
try except

使用
请求对用户有什么好处?更容易忽略
请求
并支持标准库函数。这可以通过如下方式导入,对代码的其余部分透明:

try:
    from urllib.request import urlopen
except ImportError:
    from urllib2 import urlopen
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()
从那时起,所有GET请求都可以通过
urlopen(url)
发出。可以使用
read()
检索返回的数据

现在,如果您确实想继续执行
请求
支持,您可以编写导入代码以及
get\u content()
的定义,如下所示:

try:
    from urllib.request import urlopen
except ImportError:
    from urllib2 import urlopen
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()

正如每个人都提到的,如果您使用的是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"))

您可以尝试将所有三个库作为
request
导入,并在
get\u content
函数中检查属性以识别导入的库。
作为嵌套的try-except块的替代方法,您可以在单独的try-except块中导入
请求
, 这样,如果安装了模块,它将覆盖
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()

如果您不想将
请求
作为依赖项,为什么还要麻烦使用
请求
?如果您要让它单独使用
urllib
,只需使用
urllib
。我认为您已经掌握了Python2和Python3的要点。因此建议使用
请求
。但是,请参见“#Python 2和3:alternative 4”中的
urllib
——对于
导入
,只有
尝试