code: def split_input(cls, mapper_spec, _reader=blobstore.BlobReader):
      
      params = _get_params(mapper_spec)
      blob_key = params[cls.BLOB_KEY_PARAM]
      zip_input = zipfile.ZipFile(_reader(blob_key))
      zfiles = zip_input.infolist()
      total_size = sum(x.file_size for x in zfiles)
      num_shards = min(mapper_spec.shard_count, cls._MAX_SHARD_COUNT)
      size_per_shard = total_size // num_shards
  
      # Break the list of files into sublists, each of approximately
      # size_per_shard bytes.
      shard_start_indexes = [0]
      current_shard_size = 0
      for i, fileinfo in enumerate(zfiles):
        current_shard_size += fileinfo.file_size
        if current_shard_size >= size_per_shard:
          shard_start_indexes.append(i + 1)
          current_shard_size = 0
  
      if shard_start_indexes[-1] != len(zfiles):
        shard_start_indexes.append(len(zfiles))
  
      return [cls(blob_key, start_index, end_index, _reader)
              for start_index, end_index
              in zip(shard_start_indexes, shard_start_indexes[1:])]
docs: Returns a list of input shard states for the input spec.
  
      Args:
        mapper_spec: The MapperSpec for this InputReader. Must contain
            'blob_key' parameter with one blob key.
        _reader: a callable that returns a file-like object for reading blobs.
            Used for dependency injection.
  
      Returns:
        A list of InputReaders spanning files within the zip.