docs: def run_multiple_grid_districts(mv_grid_districts, run_id, failsafe=False,
                                  base_path=None):
      """
      Perform ding0 run on given grid districts
  
      Parameters
      ----------
      mv_grid_districs : list
          Integers describing grid districts
      run_id: str
          Identifier for a run of Ding0. For example it is used to create a
          subdirectory of os.path.join(`base_path`, 'results')
      failsafe : bool
          Setting to True enables failsafe mode where corrupt grid districts
          (mostly due to data issues) are reported and skipped. Report is to be
           found in the log dir under :code:`~/.ding0` . Default is False.
      base_path : str
          Base path for ding0 data (input, results and logs).
          Default is `None` which sets it to :code:`~/.ding0` (may deviate on
          windows systems).
          Specify your own but keep in mind that it a required a particular
          structure of subdirectories.
  
      Returns
      -------
      msg : str
          Traceback of error computing corrupt MV grid district
          .. TODO: this is only true if try-except environment is moved into this
              fundion and traceback return is implemented
  
      Notes
      -----
      Consider that a large amount of MV grid districts may take hours or up to
      days to compute. A computational run for a single grid district may consume
      around 30 secs.
      """
      start = time.time()
  
      # define base path
      if base_path is None:
          base_path = BASEPATH
  
      # database connection/ session
      engine = db.connection(section='oedb')
      session = sessionmaker(bind=engine)()
  
      corrupt_grid_districts = pd.DataFrame(columns=['id', 'message'])
  
      for mvgd in mv_grid_districts:
          # instantiate ding0  network object
          nd = NetworkDing0(name='network', run_id=run_id)
  
          if not os.path.exists(os.path.join(base_path, "grids")):
              os.mkdir(os.path.join(base_path, "grids"))
  
          if not failsafe:
              # run DING0 on selected MV Grid District
              msg = nd.run_ding0(session=session,
                                 mv_grid_districts_no=[mvgd])
  
              # save results
              results.save_nd_to_pickle(nd, os.path.join(base_path, "grids"))
          else:
              # try to perform ding0 run on grid district
              try:
                  msg = nd.run_ding0(session=session,
                                     mv_grid_districts_no=[mvgd])
                  # if not successful, put grid district to report
                  if msg:
                      corrupt_grid_districts = corrupt_grid_districts.append(
                          pd.Series({'id': mvgd,
                                     'message': msg[0]}),
                          ignore_index=True)
                  # if successful, save results
                  else:
                      results.save_nd_to_pickle(nd, os.path.join(base_path,
                                                                 "grids"))
              except Exception as e:
                  corrupt_grid_districts = corrupt_grid_districts.append(
                      pd.Series({'id': mvgd,
                                 'message': e}),
                      ignore_index=True)
  
                  continue
  
          # Merge metadata of multiple runs
          if 'metadata' not in locals():
              metadata = nd.metadata
  
          else:
              if isinstance(mvgd, list):
                  metadata['mv_grid_districts'].extend(mvgd)
              else:
                  metadata['mv_grid_districts'].append(mvgd)
  
      # Save metadata to disk
      with open(os.path.join(base_path, "grids", 'Ding0_{}.meta'.format(run_id)),
                'w') as f:
          json.dump(metadata, f)
  
      # report on unsuccessful runs
      corrupt_grid_districts.to_csv(
          os.path.join(
              base_path,
              "grids",
              'corrupt_mv_grid_districts.txt'),
          index=False,
          float_format='%.0f')
  
      print('Elapsed time for', str(len(mv_grid_districts)),
            'MV grid districts (seconds): {}'.format(time.time() - start))
  
      return msg