code: def save(self, client=None):
          
          if not client:
              client = Panoptes.client()
  
          async_save = hasattr(self._local, 'save_exec')
  
          with client:
              if async_save:
                  try:
                      # The recursive call will exec in a new thread, so
                      # self._local.save_exec will be undefined above
                      self._async_future = self._local.save_exec.submit(
                          self.save,
                          client=client,
                      )
                      return
                  except RuntimeError:
                      del self._local.save_exec
                      async_save = False
  
              if not self.metadata == self._original_metadata:
                  self.modified_attributes.add('metadata')
  
              response = retry(
                  super(Subject, self).save,
                  attempts=UPLOAD_RETRY_LIMIT,
                  sleeptime=RETRY_BACKOFF_INTERVAL,
                  retry_exceptions=(PanoptesAPIException,),
                  log_args=False,
              )
  
              if not response:
                  return
  
              try:
                  if async_save:
                      upload_exec = self._local.save_exec
                  else:
                      upload_exec = ThreadPoolExecutor(
                          max_workers=ASYNC_SAVE_THREADS,
                      )
  
                  for location, media_data in zip(
                      response['subjects'][0]['locations'],
                      self._media_files
                  ):
                      if not media_data:
                          continue
  
                      for media_type, url in location.items():
                          upload_exec.submit(
                              retry,
                              self._upload_media,
                              args=(url, media_data, media_type),
                              attempts=UPLOAD_RETRY_LIMIT,
                              sleeptime=RETRY_BACKOFF_INTERVAL,
                              retry_exceptions=(
                                  requests.exceptions.RequestException,
                              ),
                              log_args=False,
                          )
              finally:
                  if not async_save:
                      upload_exec.shutdown()
docs: Like :py:meth:`.PanoptesObject.save`, but also uploads any local files
          which have previosly been added to the subject with
          :py:meth:`add_location`. Automatically retries uploads on error.
  
          If multiple local files are to be uploaded, several files will be
          uploaded simultaneously to save time.