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协议的方法了,然后就知道识别找方法。