python build custom callback function detail

  • 2020-06-07 04:41:52
  • OfStack

Callbacks are nice to use. Especially in js, where the world is full of callbacks, how do you gracefully implement your own callbacks in python

Let me post an example of what I wrote


class BaseHandler(object):

  def crawl(self, url, **kwargs):
    if kwargs.get('callback'):
      callback = kwargs['callback']
      if isinstance(callback, basestring) and hasattr(self, callback):
        func = getattr(self, callback)
      elif hasattr(callback, 'im_self') and callback.im_self is self:
        func = callback

    resp = requests.get(url)
    return func(resp)


class Anjuke(BaseHandler):
  def on_start(self):
    self.crawl(start_url, callback=self.index_url)

  def index_url(self, response):
    print response.text

a = Anjuke()
print a.on_start()

In fact, the object/string of callback is obtained by kwargs, and then the callback method is reflected by getattr(self, callback), and then called.

You can then take a step further and increase the reuse of callback methods so that BaseHandler can be rewritten as decorator


def callback(f):
  def wrapper(obj, *args, **kwargs):
    resp = f(obj, *args, **kwargs)
    if kwargs.get('callback'):
      mcallback = kwargs['callback']
      if isinstance(callback, basestring) and hasattr(obj, mcallback):
        func = getattr(obj, mcallback)
      elif hasattr(mcallback, 'im_self') and mcallback.im_self is obj:
        func = mcallback
        kwargs['callback'] = func.__name__
      else:
        raise NotImplementedError("self.%s() not implemented!" % callback)

    return func(resp)
  return wrapper


class BaseHandler(object):

  @callback
  def crawl(self, url, **kwargs):
    url = quote_chinese(_build_url(url.strip(), kwargs.get('params')))
    return requests.get(url)


Related articles: