Pure Python
Flyte 2 introduces a new way of writing workflows that is based on pure Python, removing the constraints of a domain-specific language (DSL) and enabling full use of Python’s capabilities.
From @workflow DSL to pure Python
| Flyte 1 | Flyte 2 |
|---|---|
@workflow-decorated functions are constrained to a subset of Python for defining a static directed acyclic graph (DAG) of tasks. |
No more @workflow decorator: Everything is a @env.task, so your top-level “workflow” is simply a task that calls other tasks. |
@task-decorated functions could leverage the full power of Python, but only within individual container executions. |
@env.tasks can call other @env.tasks and be used to construct workflows with dynamic structures using loops, conditionals, try/except, and any Python construct anywhere. |
| Workflows were compiled into static DAGs at registration time, with tasks as the nodes and the DSL defining the structure. | Workflows are simply tasks that call other tasks. Compile-time safety will be available in the future as compiled_task. |
import flytekit
image = flytekit.ImageSpec(
name="hello-world-image",
packages=["requests"],
)
@flytekit.task(container_image=image)
def mean(data: list[float]) -> float:
return sum(list) / len(list)
@flytekit.workflow
def main(data: list[float]) -> float:
output = mean(data)
# ❌ performing trivial operations in a workflow is not allowed
# output = output / 100
# ❌ if/else is not allowed
# if output < 0:
# raise ValueError("Output cannot be negative")
return output
import flyte
env = flyte.TaskEnvironment(
"hello_world",
image=flyte.Image.from_debian_base().with_pip_packages("requests"),
)
@env.task
def mean(data: list[float]) -> float:
return sum(data) / len(data)
@env.task
def main(data: list[float]) -> float:
output = mean(data)
# ✅ performing trivial operations in a workflow is allowed
output = output / 100
# ✅ if/else is allowed
if output < 0:
raise ValueError("Output cannot be negative")
return output
These fundamental changes bring several transformative benefits:
- Flexibility: Harness the complete Python language for workflow definition, including all control flow constructs previously forbidden in workflows.
- Dynamic workflows: Create workflows that adapt to runtime conditions, handle variable data structures, and make decisions based on intermediate results.
- Natural error handling: Use standard Python
try/exceptpatterns throughout your workflows, making them more robust and easier to debug. - Intuitive composability: Build complex workflows by naturally composing Python functions, following familiar patterns that any Python developer understands.