class URLopener: def __init__(self, proxies=None,**x509): def __del__(self): def close(self): def cleanup(self): def addheader(self,*args): def open(self, fullurl, data=None): def open_unknown(self, fullurl, data=None): def open_unknown_proxy(self, proxy, fullurl, data=None): def retrieve(self, url, filename=None, reporthook=None, data=None): def open_http(self, url, data=None): def http_error(self, url, fp, errcode, errmsg, headers, data=None): def http_error_default(self, url, fp, errcode, errmsg, headers): def open_https(self, url, data=None): def open_file(self, url): def open_local_file(self, url): def open_ftp(self, url): def open_data(self, url, data=None):
该类的设计逻辑是不管37是否等于21,先实例化该类对象出来,如果有代理,在实例化的时候将代理制定给这个实例化对象的一个属性,然后直接调用这个类的open方法,open方法里面有很多处理逻辑,比如,通过你给定url来判断要使用什么协议来对这个url进行处理,调用本类中的那个方法。
设计中的一个经典核心代码:
urltype, url = splittype(fullurl)#解析url,分析出该url的特点,比如file,ftp,http,等
if not urltype:
urltype = 'file'
if urltype in self.proxies:
proxy = self.proxies[urltype]
urltype, proxyhost = splittype(proxy)
host, selector = splithost(proxyhost)
url = (host, fullurl) # Signal special case to open_*()
else:
proxy = None
name = 'open_' + urltype
self.type = urltype
name = name.replace('-', '_')
if not hasattr(self, name):
if proxy:
return self.open_unknown_proxy(proxy, fullurl, data)
else:
return self.open_unknown(fullurl, data)
try:
if data is None:
#getattr()方法,如果name(形如'open_http','open_ftp','open_local_file')为真,返回这个属性,
#即调用了这个方法,并且url是他传入的一个参数!从该类中其他方法名可以看出作者就是这个意思。
return getattr(self, name)(url)
else:
return getattr(self, name)(url, data)
except socket.error, msg:
raise IOError, ('socket error', msg), sys.exc_info()[2]
调用到符合url协议的方法了,然后就知道识别找方法。