def read_multi(flatten, cls, source, *args, **kwargs):
verbose = kwargs.pop('<STR_LIT>', False)<EOL>try:  <EOL><INDENT>files = file_list(source)<EOL><DEDENT>except ValueError:  <EOL><INDENT>files = [source]<EOL>path = None  <EOL><DEDENT>else:<EOL><INDENT>path = files[<NUM_LIT:0>] if files else None<EOL><DEDENT>if kwargs.get('<STR_LIT>', None) is None:<EOL><INDENT>kwargs['<STR_LIT>'] = get_read_format(cls, path, (source,) + args, kwargs)<EOL><DEDENT>nproc = min(kwargs.pop('<STR_LIT>', <NUM_LIT:1>), len(files))<EOL>def _read_single_file(fobj):<EOL><INDENT>try:<EOL><INDENT>return fobj, io_read(cls, fobj, *args, **kwargs)<EOL><DEDENT>except Exception as exc:<EOL><INDENT>if nproc == <NUM_LIT:1>:<EOL><INDENT>raise<EOL><DEDENT>if isinstance(exc, SAXException):  <EOL><INDENT>return fobj, exc.getException()  <EOL><DEDENT>return fobj, exc<EOL><DEDENT><DEDENT>if verbose is True:<EOL><INDENT>verbose = '<STR_LIT>'.format(kwargs['<STR_LIT>'])<EOL><DEDENT>output = mp_utils.multiprocess_with_queues(<EOL>nproc, _read_single_file, files, verbose=verbose, unit='<STR_LIT>')<EOL>for fobj, exc in output:<EOL><INDENT>if isinstance(exc, Exception):<EOL><INDENT>exc.args = ('<STR_LIT>' % (fobj, str(exc)),)<EOL>raise exc<EOL><DEDENT><DEDENT>_, out = zip(*output)<EOL>return flatten(out)<EOL>
Read sources into a `cls` with multiprocessing

    This method should be called by `cls.read` and uses the `nproc`
    keyword to enable and handle pool-based multiprocessing of
    multiple source files, using `flatten` to combine the
    chunked data into a single object of the correct type.

    Parameters
    ----------
    flatten : `callable`
        a method to take a list of ``cls`` instances, and combine them
        into a single ``cls`` instance

    cls : `type`
        the object type to read

    source : `str`, `list` of `str`, ...
        the input data source, can be of in many different forms

    *args
        positional arguments to pass to the reader

    **kwargs
        keyword arguments to pass to the reader