Executes the processor passing given arguments.

        :param args: a list of parameters in --key=value format.

def invoke(proc, args=None, *, _instance = None, **kwargs):
        """
        Executes the processor passing given arguments.

        :param args: a list of parameters in --key=value format.
        """
        if args is None:
            args=[]
        for kwargname in kwargs:
            args.append('--'+kwargname)
            args.append('{}'.format(kwargs[kwargname]))
        parser = proc.invoke_parser(noexit=(_instance is not None))
        opts = parser.parse_args(args)
        kwargs0 = {}


        def handle_set(opts, dataset, kwargs0, canMulti = False):
            for elem in dataset:
                elemname = elem.name
                # ml-run-process passes values for not provided inputs, outputs and params as empty strings ('')
                if hasattr(opts, elemname) and getattr(opts, elemname) not in [None, '']:
                    # value for element was given in the invocation
                    elemvalue = getattr(opts, elemname)
                    if canMulti and isinstance(elemvalue, list):
                        elemlist = elemvalue
                    else:
                        elemlist = [ elemvalue ]
                    for elemelem in elemlist:
                        for validator in elem.validators: validator(elemelem)
                    if hasattr(opts, elem.name):
                        prepared = elem.prepare(elemvalue) or elemvalue
                        kwargs0[elem.name] = prepared
                elif elem.optional:
                    # value was not set but is optional so ignore it
                    kwargs0[elem.name] = None
                else:
                    # value was not set and is mandatory -- error
                    raise AttributeError('Missing value for {} '.format(elemname))

        try:
            handle_set(opts, proc.INPUTS, kwargs0, True)
            handle_set(opts, proc.OUTPUTS, kwargs0, True)

            for param in proc.PARAMETERS:
                if hasattr(opts, param.name) and getattr(opts, param.name) is not None and getattr(opts, param.name) is not '':
                    value = getattr(opts, param.name)
                    # validate if needed
                    for validator in param.validators:
                        validator(value)
                    # if param is a tuple of choices, each choice is a tuple itself
                    # with first element of the input value and second element
                    # containing the value to be passed to the processor
                    if param.choices and isinstance(param.choices, tuple):
                        for choice in param.choices:
                            if choice[0] == value:
                                kwargs0[param.name] = choice[1]
                                break
                    else:
                        kwargs0[param.name] = value
                elif param.optional:
                    kwargs0[param.name] = param.default
                else:
                    raise AttributeError('Missing value for {} parameter'.format(param.name))
            if not _instance:
                _instance = proc(**kwargs0)
            else:
                _instance.apply(_instance, **kwargs0)
            return _instance.run()
            # todo: cleanup
        except Exception as e:
            print("Error:", e)
#            traceback.print_exc()
            raise