使用 urllib、urllib2 和 request 避免 "Pyramid of Doom" 之类的语法
Avoiding the "Pyramid of Doom" like syntax with urllib, urllib2 and request
很难为响应编写 Python2 和 Python3 以及 request
依赖代码,因为它们 urlopen()
函数和 requests.get()
函数 return 不同类型:
- Python2
urllib.request.urlopen()
return一个http.client.HTTPResponse
- Python3
urllib.urlopen(url)
return 一个 instance
- 请求
request.get(url)
return一个requests.models.Response
为了同时支持 Python2 和 Python3 以及不想安装 request
依赖项的用户,我尝试了 "Pyramid of Doom" 看起来 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.
是否有其他方法可以达到 return读取内容并避免嵌套 try-except
的相同结果?
您的用户使用 requests
有什么好处?简单地忽略 requests
并支持标准库函数会更容易。这可以通过像这样导入对其余代码透明地完成:
try:
from urllib.request import urlopen
except ImportError:
from urllib2 import urlopen
从那时起,所有 GET 请求都可以用 urlopen(url)
发出。可以使用 read()
.
检索返回的数据
现在,如果您真的想继续 requests
支持,您可以像这样将导入代码与 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()
正如每个人都提到的,如果你走的是 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_content
函数中的属性以识别导入的库。
作为嵌套 try-except 块的替代方案,您可以在单独的 try-except 块中导入 requests
,
如果安装了模块,它将覆盖 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()
这会产生干净简单的代码,并允许您提交更复杂的请求,例如,
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()
很难为响应编写 Python2 和 Python3 以及 request
依赖代码,因为它们 urlopen()
函数和 requests.get()
函数 return 不同类型:
- Python2
urllib.request.urlopen()
return一个http.client.HTTPResponse
- Python3
urllib.urlopen(url)
return 一个instance
- 请求
request.get(url)
return一个requests.models.Response
为了同时支持 Python2 和 Python3 以及不想安装 request
依赖项的用户,我尝试了 "Pyramid of Doom" 看起来 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.
是否有其他方法可以达到 return读取内容并避免嵌套 try-except
的相同结果?
您的用户使用 requests
有什么好处?简单地忽略 requests
并支持标准库函数会更容易。这可以通过像这样导入对其余代码透明地完成:
try:
from urllib.request import urlopen
except ImportError:
from urllib2 import urlopen
从那时起,所有 GET 请求都可以用 urlopen(url)
发出。可以使用 read()
.
现在,如果您真的想继续 requests
支持,您可以像这样将导入代码与 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()
正如每个人都提到的,如果你走的是 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_content
函数中的属性以识别导入的库。
作为嵌套 try-except 块的替代方案,您可以在单独的 try-except 块中导入 requests
,
如果安装了模块,它将覆盖 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()
这会产生干净简单的代码,并允许您提交更复杂的请求,例如,
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()