A Little Study on Requests

Overview

Requests is a great python lib to handle http calls, it is simple and intuitive to use. But when actually implement your class, to handle exceptions raised by Requests, the official document seems to be a little slim on it. First, unlike urllib2, Requests does not treat http errors as exceptions (it has a status_code to reflect the error, but won’t actually raise the exception flag). So I implement a customized error class, combined with a if condition statement, I manage to catch the http error as an exception.

Python code

import requests
class APIError(StandardError):
    def __init__(self, error_code, error, request):
        self.error_code = error_code #code
        self.error = error #msg
        self.request = request
        StandardError.__init__(self, error)

    def __unicode__(self):
        return u'APIError: %s: %s, request: %s' % (self.error_code, self.error, self.request)

def c():
    access_token = YOUR_TOKEN
    url = 'https://api.douban.com/shuo/v2/statuses/'
    v = {'text':'hello'}
    h = {'Authorization':'Bearer %s' % access_token}
    try:
        r = requests.post(url, data=v, headers = h)
	rr = r.json()
	# example error response
	#{"msg":"\u9700\u8981\u767b\u5f55","code":1000}
	#{'msg': invalid_access_token: YOUR_TOKEN', 'code': 103, 'request': 'POST /shuo/v2/statuses/'}
	if rr.__contains__('code'):
	    raise APIError(rr['code'], rr.get('msg', ''), rr.get('request', ''))
	return rr
    except requests.exceptions.ConnectionError, e:
	print '%s' %e # for debuggin
	raise APIError(u'requests.exceptions.ConnectionError', e, 'request: %s'%url)
    except requests.exceptions.RequestException, e:
	print '!%s' %e # for debuggin
	raise APIError(u'requests.exceptions.RequestException', e, 'request: %s'%url)
    except requests.exceptions.TooManyRedirects, e:
	print '!!%s' %e # for debuggin
	raise APIError(u'requests.exceptions.TooManyRedirects', e, 'request: %s'%url)
    except requests.exceptions.URLRequired, e:
	print '!!!url missing %s' % e # for debuggin
	raise APIError(u'requests.exceptions.URLRequired', e, 'request: %s'%url)
    except APIError, e:
        print 'customized error'
	raise APIError(e.error_code, e.error, e.request)
    except Exception, err:
	print "renren_http_call: unexpected error %s" %err
	raise APIError(u'unkown code', str(err), type(err))

def d():
    try:
	r = c()
	return r
    except APIError, e:
	print type(e)
	print e.error_code
	print e.error
	print e.request

c() is the child function that actually takes care of the requests calling. If in the response dictionary, there is a ‘code’ key, (or you could use r.status_code != 200), that means there is a http error, and we could raise our customized error class to pass alone the error information to the mother function (or class), in our case, the function d().
and in d()’s exception handling, you could deal with different situations by implement if condition statement, in the example code, I just print out the message for demo purpose.
Hope this helps, enjoy :)

August 14, 2013

Comments

comments powered by Disqus