class_docstr: Similar to :class:`MultiProcessMapDataZMQ`, except that this DataFlow
  also does batching in parallel in the worker processes.
  Therefore it can be helpful if you wish to hide the latency of batching.
  
  When `nr_proc==1`, the behavior of this class is identical to
  `BatchData(MapData(ds, map_func), batch_size)`.
  
  When `nr_proc>1`, the datapoints may be grouped in arbitrary order,
  or grouped with datapoints from a different pass of the given dataflow.
docstr: Args:
      ds (DataFlow): the dataflow to map
      num_proc(int): number of threads to use
      map_func (callable): datapoint -> datapoint | None. Return None to
          discard/skip the datapoint.
      batch_size (int): batch size
      buffer_size (int): number of datapoints (not batched) in the buffer.
          Defaults to batch_size * 10
docstr_tok: ["Args",":","ds","(","DataFlow",")",":","the","dataflow","to","map","num_proc","(","int",")",":","number","of","threads","to","use","map_func","(","callable",")",":","datapoint","-",">","datapoint","|","None",".","Return","None","to","discard\/skip","the","datapoint",".","batch_size","(","int",")",":","batch","size","buffer_size","(","int",")",":","number","of","datapoints","(","not","batched",")","in","the","buffer",".","Defaults","to","batch_size","*","10"]
code: def __init__(
      self, ds, num_proc, map_func, batch_size, buffer_size=None
  ):
      """
      Args:
          ds (DataFlow): the dataflow to map
          num_proc(int): number of threads to use
          map_func (callable): datapoint -> datapoint | None. Return None to
              discard/skip the datapoint.
          batch_size (int): batch size
          buffer_size (int): number of datapoints (not batched) in the buffer.
              Defaults to batch_size * 10
      """
      super(MultiProcessMapAndBatchDataZMQ, self).__init__()
      assert batch_size < buffer_size
      self.ds = ds
      self.num_proc = num_proc
      self.map_func = map_func
      self.batch_size = batch_size
      if buffer_size is None:
          buffer_size = batch_size * 10
      self.buffer_size = buffer_size
  
imports: import copy
  import ctypes
  import multiprocessing
  import numpy
  import threading
  import zmq
  from six.moves import queue
  from ..utils.concurrency import StoppableThread, enable_death_signal
  from ..utils.serialize import dumps_once, loads_once
  from .base import DataFlow, DataFlowReentrantGuard, ProxyDataFlow
  from .common import RepeatedData, BatchData
  from .parallel import _bind_guard, _get_pipe_name, _MultiProcessZMQDataFlow, _repeat_iter, _zmq_catch_error
label_desc: Use image node_id 1 to create a new MultiProcessMapAndBatchDataZMQ object from inherited base classes: _MultiProcessZMQDataFlow with example: obj = MultiProcessMapAndBatchDataZMQ(ds, num_proc, map_func, batch_size, buffer_size)