code: def log_future_exceptions(logger, f, ignore=()):
      
      def log_cb(f):
          try:
              f.result()
          except ignore:
              pass
          except Exception:
              logger.exception('Unhandled exception returned by future')
      f.add_done_callback(log_cb)
docs: Log any exceptions set to a future
  
      Parameters
      ----------
      logger : logging.Logger instance
          logger.exception(...) is called if the future resolves with an exception
      f : Future object
          Future to be monitored for exceptions
      ignore : Exception or tuple of Exception
          Exptected exception(s) to ignore, i.e. they will not be logged.
  
      Notes
      -----
      This is useful when an async task is started for its side effects without waiting for
      the result. The problem is that if the future's resolution is not checked for
      exceptions, unhandled exceptions in the async task will be silently ignored.