Handles pushing out the task and getting the response. Can be called 
        directly to wait for the response.
        
        task -- the server-side identifier for the desired task
        *args and **kw will be passed to the task on the server-side.
        
        Return value is generally the same as on the server-side, so if the 
        server has a task for list() named 'list', calling 
          frontend.work('list', '123456')
        should return
          ['1', '2', '3', '4', '5', '6']
        
        All errors are converted into informational BackendProcessingError()s; 
        for example, following the example above,
          frontend.work('list', 42)
        should raise
          BackendProcessingError('TypeError', ["'int' object is not iterable"])
        Which could then be inspected:
          >>> e.type
          'TypeError'
          >>> e.args
          ["'int' object is not iterable"]

def work(self, task, *args, **kw):
        """
        Handles pushing out the task and getting the response. Can be called 
        directly to wait for the response.
        
        task -- the server-side identifier for the desired task
        *args and **kw will be passed to the task on the server-side.
        
        Return value is generally the same as on the server-side, so if the 
        server has a task for list() named 'list', calling 
          frontend.work('list', '123456')
        should return
          ['1', '2', '3', '4', '5', '6']
        
        All errors are converted into informational BackendProcessingError()s; 
        for example, following the example above,
          frontend.work('list', 42)
        should raise
          BackendProcessingError('TypeError', ["'int' object is not iterable"])
        Which could then be inspected:
          >>> e.type
          'TypeError'
          >>> e.args
          ["'int' object is not iterable"]
        """
        package = self._package(task, *args, **kw)
        backends = sorted(self.backends, key=self._sorter)
        
        for backend in backends:
            try:
                return self._work(backend, package, task)
            except socket.error:
                # We want to just move onto the next backend if we couldn't 
                # connect to this one
                pass
        # Didn't not get a backend, let the caller know!
        raise BackendNotAvailableError