Executor File Structure

Besides organizing your Executor code inline-ly (i.e. with Flow.add() in the same file), you can also write it as an “external” module and then use it via YAML. This is useful when your Executor’s logic is too complicated to fit into a single file.

Inline manner

  1. from jina import Executor, Flow, Document, requests
  2. class MyExecutor(Executor):
  3. @requests
  4. def foo(self, **kwargs):
  5. print(kwargs)
  6. f = Flow().add(uses=MyExecutor)
  7. with f:
  8. f.post(on='/random_work', inputs=Document(), on_done=print)

Separate module

foo.py

Executor File Structure - 图1

Executor File Structure - 图2

  1. from jina import Executor, Flow, Document, requests
  2. class MyExecutor(Executor):
  3. @requests
  4. def foo(self, **kwargs):
  5. print(kwargs)
  6. f = Flow().add(uses=MyExecutor)
  7. with f:
  8. f.post(on='/random_work', inputs=Document(), on_done=print)
  9. ``` my.yml
  10. ![](/projects/jina-2.7.0-en/560a334f905a2c3f3a88dc4cbf6917b0.svg)
  11. ![](/projects/jina-2.7.0-en/7d4a10a8b8976688e4d950af40acec01.svg)

jtype: MyExecutor metas: py_modules:

  1. - foo.py

name: awesomeness description: my first awesome executor requests: /random_work: foo

  1. ![](/projects/jina-2.7.0-en/560a334f905a2c3f3a88dc4cbf6917b0.svg)
  2. ![](/projects/jina-2.7.0-en/7d4a10a8b8976688e4d950af40acec01.svg)

from jina import Flow, Document

f = Flow().add(uses=’my.yml’)

with f: f.post(on=’/random_work’, inputs=Document(), on_done=print)

  1. ## Single Python file
  2. When you are only working with a single python file (lets call it `my_executor.py`), you can simply put it at the root of the repository, and import it directly in `config.yml`

jtype: MyExecutor metas: py_modules:

  1. - my_executor.py
  1. ## Multiple Python files
  2. When you are working with multiple python files, you should organize them as a **Python package** and put them in a special folder inside your repository (as you would normally do with Python packages). Specifically, you should do the following:
  3. - put all your Python files inside a special folder (call it `executor`, as a convention), and put an `__init__.py` file inside it
  4. - because of how Jina registers executors, make sure to import your executor in this file (see the contents of `executor/__init__.py` in the example below).
  5. - use relative imports (`from .bar import foo`, and not `from bar import foo`) inside the python modules in this folder
  6. - Only list `executor/__init__.py` under `py_modules` in `config.yml` - this way Python knows that you are importing a package, and makes sure that all the relative imports within your package work properly
  7. To make things more specific, take this repository structure as an example:

. ├── config.yml └── executor ├── helper.py ├── init.py └── my_executor.py

  1. The contents of `executor/__init__.py` is

from .my_executor import MyExecutor

  1. the contents of `executor/helper.py` is

def print_something(): print(‘something’)

  1. and the contents of `executor/my_executor.py` is

from jina import Executor, requests

from .helper import print_something

class MyExecutor(Executor): @requests def foo(self, **kwargs): print_something()

  1. Finally, the contents of `config.yml` - notice that only the `executor/__init__.py` file needs to be listed under `py_modules`

jtype: MyExecutor metas: py_modules:

  1. - executor/__init__.py
  1. This was a relatively simple example, but this way of structuring python modules works for any python package structure, however complex. Consider this slightly more complicated example

. ├── config.yml # Remains exactly the same as before └── executor ├── helper.py ├── init.py ├── myexecutor.py └── utils/ ├── _init.py # Required inside all executor sub-folders ├── data.py └── io.py ```

Here you can then import from utils/data.py in my_executor.py like this: from .utils.data import foo, and do any other kinds of relative imports that python enables.

The best thing is that no matter how complicated your package structure, “importing” it in your config.yml file is super easy - you always put only executor/__init__.py under py_modules.

Hint

For a remote Executor used with JinaD, please read the guidelines about uploading files to remote.