def open_url(self, url, headers):
        """ open url with python libraries
        """
        
        data = self.cache.get_cached_data(url)
        if data is not None:
            return data, 200, headers
        
        self.rate_limit_ensembl_requests()
        req = request.Request(url, headers=headers)
        
        try:
            handler = request.urlopen(req)
        except HTTPError as error:
            # if we get a http error, we still process the status code, since a
            # later step deals with different status codes differently.
            handler = error
        except (URLError, ConnectionResetError, TimeoutError):
            # if we get a ConnectionResetError, assume something has gone wrong
            # with the server. Later code will wait before retrying.
            return '', 500, headers
        
        status_code = handler.getcode()
        response = handler.read()
        if IS_PYTHON3:
            response = response.decode("utf-8")
        
        # parse the headers into a key, value dictionary
        headers = dict(zip(map(str.lower, handler.headers.keys()), handler.headers.values()))
        
        now = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime())
        logging.warning("{}\t{}\t{}".format(now, status_code, url))
        
        return response, status_code, headers
open url with python libraries