code: def data_iterator(
      data_source,
      batch_size,
      rng=None,
      use_thread=True,
      with_memory_cache=True,
      with_file_cache=False,
      cache_dir=None,
      epoch_begin_callbacks=[],
      epoch_end_callbacks=[],
      stop_exhausted=False,
  ):
      """data_iterator
      Helper method to use :py:class:`DataSource <nnabla.utils.data_source.DataSource>`.
  
      You can use :py:class:`DataIterator <nnabla.utils.data_iterator.DataIterator>` with your own :py:class:`DataSource <nnabla.utils.data_source.DataSource>`
      for easy implementation of data sources.
  
      For example,
  
      .. code-block:: python
  
          ds = YourOwnImplementationOfDataSource()
          batch = data_iterator(ds, batch_size)
  
  
      Args:
          data_source (:py:class:`DataSource <nnabla.utils.data_source.DataSource>`):
               Instance of DataSource class which provides data.
          batch_size (int): Batch size.
          rng (None or :obj:`numpy.random.RandomState`): Numpy random number
              generator.
          use_thread (bool):
              If ``use_thread`` is set to True, iterator will use another thread to
              fetch data. If ``use_thread`` is set to False, iterator will use
              current thread to fetch data.
          with_memory_cache (bool):
              If ``True``, use :py:class:`.data_source.DataSourceWithMemoryCache`
              to wrap ``data_source``. It is a good idea to set this as true unless
              data_source provides on-memory data.
              Default value is True.
          with_file_cache (bool):
              If ``True``, use :py:class:`.data_source.DataSourceWithFileCache`
              to wrap ``data_source``.
              If ``data_source`` is slow, enabling this option a is good idea.
              Default value is False.
          cache_dir (str):
              Location of file_cache.
              If this value is None, :py:class:`.data_source.DataSourceWithFileCache`
              creates file caches implicitly on temporary directory and erases them all
              when data_iterator is finished.
              Otherwise, :py:class:`.data_source.DataSourceWithFileCache` keeps created cache.
              Default is None.
          epoch_begin_callbacks (list of functions): An item is a function
              which takes an epoch index as an argument. These are called
              at the beginning of an epoch.
          epoch_end_callbacks (list of functions): An item is a function
              which takes an epoch index as an argument. These are called
              at the end of an epoch.
          stop_exhausted (bool): If ``stop_exhausted`` is set to False, iterator will be reset
              so that iteration can be continued. If ``stop_exhausted`` is set to True, iterator
              will raise StopIteration to stop the loop.
  
      Returns:
          :py:class:`DataIterator <nnabla.utils.data_iterator.DataIterator>`:
              Instance of DataIterator.
      """
      if with_file_cache:
          ds = DataSourceWithFileCache(
              data_source=data_source,
              cache_dir=cache_dir,
              shuffle=data_source.shuffle,
              rng=rng,
          )
          if with_memory_cache:
              ds = DataSourceWithMemoryCache(
                  ds, shuffle=ds.shuffle, rng=rng
              )
          return DataIterator(
              ds,
              batch_size,
              use_thread=use_thread,
              epoch_begin_callbacks=epoch_begin_callbacks,
              epoch_end_callbacks=epoch_end_callbacks,
              stop_exhausted=stop_exhausted,
          )
      else:
          if with_memory_cache:
              data_source = DataSourceWithMemoryCache(
                  data_source, shuffle=data_source.shuffle, rng=rng
              )
          return DataIterator(
              data_source,
              batch_size,
              use_thread=use_thread,
              epoch_begin_callbacks=epoch_begin_callbacks,
              epoch_end_callbacks=epoch_end_callbacks,
              stop_exhausted=stop_exhausted,
          )
  
imports: import atexit
  import threading
  import queue
  import numpy
  import six
  from nnabla.logger import logger
  from .data_source import DataSourceWithFileCache
  from .data_source import DataSourceWithMemoryCache
  from .data_source import SlicedDataSource
  from .data_source_implements import CacheDataSource
  from .data_source_implements import ConcatDataSource
  from .data_source_implements import CsvDataSource
  from .data_source_implements import SimpleDataSource
label_desc: Use image node_id 1 for calling a global function with example usage: data_iterator(data_source, batch_size, rng, use_thread, with_memory_cache, with_file_cache, cache_dir, epoch_begin_callbacks, epoch_end_callbacks, stop_exhausted) and returns: DataIterator, DataIterator