Hello World

Let’s start with a very simple example: a workflow that generates the text “Hello world!”

(The code for this example is available in the Bionic repo at example/hello_world.py.)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
from __future__ import print_function

import bionic as bn

builder = bn.FlowBuilder('hello_world')

builder.assign('greeting', 'Hello')
builder.assign('subject', 'world')


@builder
def message(greeting, subject):
    return '{0} {1}!'.format(greeting, subject)


flow = builder.build()

if __name__ == '__main__':
    print(flow.get('message'))

This example does six things:

  1. Initialize a new FlowBuilder. We’ll use this to define the entities we care about. (An entity is like a variable. It can be defined with a fixed value, or as a function of other entities.)

  2. Define a new entity called greeting, with a fixed value of "Hello".

  3. Define another entity called subject, with a fixed value of "world".

  4. Define a third entity called message, which is constructed by taking the values of greeting and subject and combining them in a sentence. We do this by applying the @builder decorator to a function; Bionic automatically infers the name of the new entity (message) and the name of its dependencies (greeting and subject).

  5. Assemble a Flow object, which is capable of computing any of the entities we’ve defined.

  6. Use our flow to compute the message "Hello world!"

We can run this code (assuming we’ve checked out the bionic repo) like this:

> cd bionic
> python example/hello_world.py
Hello world!

We can also import it in an interpreter or notebook:

[1]:
import _tutorial_setup  # Ignore this.

from example.hello_world import flow
flow.get('message')
[1]:
'Hello world!'

Although our flow object is immutable, we can easily make a new copy with a different value of subject:

[2]:
new_flow = flow.setting('subject', 'universe')
new_flow.get('message')
[2]:
'Hello universe!'

We can also try changing the message directly:

[3]:
flow.setting('message', 'Goodbye world!').get('message')
[3]:
'Goodbye world!'

As a convenience, setting and get can be called by an alternative syntax which makes it easier for your notebook or interpreter to autocomplete entity names:

[4]:
flow.setting.subject('universe').get.message()
[4]:
'Hello universe!'

Finally, we can visualize our flow as a directed acyclic graph:

[5]:
flow.render_dag()
[5]:
../_images/tutorials_hello_world_10_0.png

This flow doesn’t do much, but it illustrates how flows can be constructed, shared, and modified. The next tutorial will demonstrate a more practical example.