Executor Features

Exception handling

Exception inside @requests decorated functions can be simply raised. The Flow will handle it.

from jina import Executor, requests, Flow
from jina.types.request import Response

class MyExecutor(Executor):

    def foo(self, **kwargs):
        raise NotImplementedError('no time for it')

f = Flow().add(uses=MyExecutor)

def print_why(resp: Response):

with f:
    f.post('', on_error=print_why)
       [email protected][L]:ready and listening
        [email protected][L]:ready and listening
           [email protected][I]:🎉 Flow is ready to use!
	🔗 Protocol: 		GRPC
	🏠 Local access:
	🔒 Private network:
	🌐 Public address:
       [email protected][E]:NotImplementedError('no time for it')
 add "--quiet-error" to suppress the exception details
Traceback (most recent call last):
  File "/Users/hanxiao/Documents/jina/jina/peapods/runtimes/zmq/zed.py", line 250, in _msg_callback
    processed_msg = self._callback(msg)
  File "/Users/hanxiao/Documents/jina/jina/peapods/runtimes/zmq/zed.py", line 236, in _callback
    msg = self._post_hook(self._handle(self._pre_hook(msg)))
  File "/Users/hanxiao/Documents/jina/jina/peapods/runtimes/zmq/zed.py", line 203, in _handle
  File "/Users/hanxiao/Documents/jina/jina/peapods/runtimes/request_handlers/data_request_handler.py", line 163, in handle
  File "/Users/hanxiao/Documents/jina/jina/executors/__init__.py", line 200, in __call__
    self, **kwargs
  File "/Users/hanxiao/Documents/jina/jina/executors/decorators.py", line 105, in arg_wrapper
    return fn(*args, **kwargs)
  File "/Users/hanxiao/Documents/jina/toy43.py", line 9, in foo
    raise NotImplementedError('no time for it')
NotImplementedError: no time for it
NotImplementedError('no time for it')

Use Executor out of Flow

Executor object can be used directly just like a regular Python object. For example,

from jina import Executor, requests, DocumentArray, Document

class MyExec(Executor):

    def foo(self, docs, **kwargs):
        for d in docs:
            d.text = 'hello world'

m = MyExec()
da = DocumentArray([Document(text='test')])
DocumentArray has 1 items:
{'id': '20213a02-bdcd-11eb-abf1-1e008a366d48', 'mime_type': 'text/plain', 'text': 'hello world'}

This is useful in debugging an Executor.

Gracefully close Executor

You might need to execute some logic when your executor’s destructor is called. For example, you want to persist data to the disk (e.g. in-memory indexed data, fine-tuned model,…). To do so, you can overwrite the method close and add your logic.

from jina import Executor, requests, Document, DocumentArray

class MyExec(Executor):

    def foo(self, docs, **kwargs):
        for doc in docs:

    def close(self):

with MyExec() as executor:
    executor.foo(DocumentArray([Document(text='hello world')]))
hello world

YAML interface

An Executor can be loaded from and stored to a YAML file. The YAML file has the following format:

jtype: MyExecutor
  parameter_1: foo
  parameter_2: bar
  name: MyExecutor
  description: "MyExecutor does a thing to the stuff in your Documents"
  workspace: workspace
    - executor.py
  index: MyExecutor_index_method
  search: MyExecutor_search_method
  random: MyExecutor_other_method
  • jtype is a string. Defines the class name, interchangeable with bang mark !;

  • with is a map. Defines kwargs of the class __init__ method

  • metas is a dictionary. It defines the meta information of that class. It contains the following fields:

    • name is a string. Defines the name of the executor;

    • description is a string. Defines the description of this executor. It will be used in automatic docs UI;

    • workspace is a string. Defines the workspace of the executor;

    • py_modules is a list of strings. Defines the Python dependencies of the executor;

  • requests is a map. Defines the mapping from endpoint to class method name;

Load and save Executor config

You can use class method Executor.load_config and object method exec.save_config to load and save YAML config:

from jina import Executor

class MyExecutor(Executor):

    def __init__(self, bar: int, **kwargs):
        self.bar = bar

    def foo(self, **kwargs):

y_literal = """
jtype: MyExecutor
  bar: 123
  name: awesomeness
  description: my first awesome executor
  /random_work: foo

exec = Executor.load_config(y_literal)

Meta attributes

By default, an Executor object contains two collections of attributes: .metas and .runtime_args. They are both in SimpleNamespace type and contain some key-value information. However, they are defined differently and serve different purposes.

  • .metas are statically defined. “Static” means, e.g. from hard-coded value in the code, from a YAML file.

  • .runtime_args are dynamically determined during runtime. Means that you don’t know the value before running the Executor, e.g. pea_id, replicas, replica_id. Those values are often related to the system/network environment around the Executor, and less about the Executor itself.

The following fields are valid for metas and runtime_args:

Attribute Fields
.metas (static values from hard-coded values, YAML config) name, description, py_modules, workspace
.runtime_args (runtime values from its containers, e.g. Runtime, Pea, Pod) name, description, workspace, log_config, quiet, quiet_error, identity, port_ctrl, ctrl_with_ipc, timeout_ctrl, ssh_server, ssh_keyfile, ssh_password, uses, py_modules, port_in, port_out, host_in, host_out, socket_in, socket_out, memory_hwm, on_error_strategy, num_part, entrypoint, docker_kwargs, pull_latest, volumes, host, port_expose, quiet_remote_logs, upload_files, workspace_id, daemon, runtime_backend, runtime_cls, timeout_ready, env, expose_public, pea_id, pea_role, noblock_on_start, uses_before, uses_after, parallel, replicas, polling, scheduling, pod_role, peas_hosts, proxy, uses_metas, external, gpus, zmq_identity, hosts_in_connect, uses_with


The YAML API will ignore .runtime_args during save and load as they are not statically stored


For any other parametrization of the Executor, you can still access its constructor arguments (defined in the class __init__) and the request parameters


workspace will be retrieved from either metas or runtime_args, in that order


Executor’s workspace is inherited according to the following rule (OR is a python or, i.e. first thing first, if NA then second):