Prefect 2.0
While you can build your task logic within a class, we recommend defining tasks as functions. Since the flow’s computational graph is discovered at runtime, there is no need for a rigid class-based task definition.
Classes are stateful, while tasks are executed in a stateless manner to support concurrency and distributed parallelism. Additionally, splitting the orchestration framework into two APIs confuses many users.
If you need to define some logic in classes, you can still either:
- call them in your functional tasks,
- initialize and invoke class methods directly in your flow
- or if you need to share state between your methods, you can build custom blocks - this series of tutorials shows how you can go about it:
How to Build a Modular Data Stack — Data Platform with Prefect, dbt and Snowflake | by Anna Geller | The Prefect Blog | Medium
Prefect 1.0
Prefect 1.0 is primarily based on a functional API with a task decorator, but it additionally allows the definition of tasks as classes with a run()
method.
Example flow using the imperative API:
from prefect import task, Task, Flow
@task # functional
def say_hello(person: str) -> None:
print("Hello, {}!".format(person))
class AddTask(Task): # imperative
def __init__(self, default: int, *args, **kwargs):
super().__init__(*args, **kwargs)
self.default = default
def run(self, x: int, y: int = None) -> int:
if y is None:
y = self.default
return x + y
# initialize the task instance
add = AddTask(default=1) # imperative
with Flow("My first flow!") as flow: # functional
first_result = add(1, y=2)
second_result = add(x=first_result, y=100)