docstr: Starts worker processes.
  
  Will block until all processes to subscribe to the worker queue (the messages are distributed by zmq on write
  so if only one, out of many, workers is up at the time of 'ventilation', the initial load won't be balanced
  between workers. If can not start the workers in timely fashion, will raise an exception.
  
  :param worker_class: A class of the worker class. The class will be instantiated in the worker process. The
      class must implement :class:`.WorkerBase` protocol.
  :param worker_setup_args: Argument that will be passed to 'args' property of the instantiated
      :class:`.WorkerBase`.
  :param ventilator: Optional ventilator to handle ventilating items to the process pool. Process pool needs
      to know about the ventilator to know if it has completed ventilating items.
  :return: ``None``
docstr_tok: ["Starts","worker","processes",".","Will","block","until","all","processes","to","subscribe","to","the","worker","queue","(","the","messages","are","distributed","by","zmq","on","write","so","if","only","one",",","out","of","many",",","workers","is","up","at","the","time","of","'ventilation","'",",","the","initial","load","wo","n't","be","balanced","between","workers",".","If","can","not","start","the","workers","in","timely","fashion",",","will","raise","an","exception",".",":","param","worker_class",":","A","class","of","the","worker","class",".","The","class","will","be","instantiated","in","the","worker","process",".","The","class","must","implement",":","class",":","`",".WorkerBase","`","protocol",".",":","param","worker_setup_args",":","Argument","that","will","be","passed","to","'args","'","property","of","the","instantiated",":","class",":","`",".WorkerBase","`",".",":","param","ventilator",":","Optional","ventilator","to","handle","ventilating","items","to","the","process","pool",".","Process","pool","needs","to","know","about","the","ventilator","to","know","if","it","has","completed","ventilating","items",".",":","return",":","``","None","``"]
code: def start(
      self, worker_class, worker_setup_args=None, ventilator=None
  ):
      """Starts worker processes.
  
      Will block until all processes to subscribe to the worker queue (the messages are distributed by zmq on write
      so if only one, out of many, workers is up at the time of 'ventilation', the initial load won't be balanced
      between workers. If can not start the workers in timely fashion, will raise an exception.
  
      :param worker_class: A class of the worker class. The class will be instantiated in the worker process. The
          class must implement :class:`.WorkerBase` protocol.
      :param worker_setup_args: Argument that will be passed to 'args' property of the instantiated
          :class:`.WorkerBase`.
      :param ventilator: Optional ventilator to handle ventilating items to the process pool. Process pool needs
          to know about the ventilator to know if it has completed ventilating items.
      :return: ``None``
      """
      # Initialize a zeromq context
      self._context = zmq.Context()
  
      # Ventilator socket used to send out tasks to workers
      (
          self._ventilator_send,
          worker_receiver_socket,
      ) = self._create_local_socket_on_random_port(
          self._context, zmq.PUSH
      )
  
      # Control socket is used to signal termination of the pool
      (
          self._control_sender,
          control_socket,
      ) = self._create_local_socket_on_random_port(
          self._context, zmq.PUB
      )
      (
          self._results_receiver,
          results_sender_socket,
      ) = self._create_local_socket_on_random_port(
          self._context, zmq.PULL
      )
  
      # We need poller to be able to read results from workers in a non-blocking manner
      self._results_receiver_poller = zmq.Poller()
      self._results_receiver_poller.register(
          self._results_receiver, zmq.POLLIN
      )
  
      # Start a bunch of processes
      self._workers = [
          exec_in_new_process(
              _worker_bootstrap,
              worker_class,
              worker_id,
              control_socket,
              worker_receiver_socket,
              results_sender_socket,
              os.getpid(),
              self._serializer,
              worker_setup_args,
          )
          for worker_id in range(self.workers_count)
      ]
  
      # Block until we have get a _WORKER_STARTED_INDICATOR from all our workers
      self._wait_for_workers_to_start()
  
      if ventilator:
          self._ventilator = ventilator
          self._ventilator.start()
  
imports: import logging
  import pickle
  import sys
  import os
  from time import sleep, time
  from traceback import format_exc
  from threading import Thread
  from psutil import pid_exists
  import zmq
  from zmq import ZMQBaseError
  from petastorm.reader_impl.pickle_serializer import PickleSerializer
  from petastorm.workers_pool import EmptyResultError, VentilatedItemProcessedMessage
  from petastorm.workers_pool.exec_in_new_process import exec_in_new_process
label_desc: Use image node_id 3 for calling the ProcessPool obj's underlying member method code with example usage: obj.start(worker_class, worker_setup_args, ventilator) without return types