Hi everyone! I'm starting to use prefect and I'm c...
# ask-community
s
Hi everyone! I'm starting to use prefect and I'm considering whether to use class based flows or the standard function based flows. For context - I have a lot of context that needs to pass in my flow like the logger, the account_id, and some other parameters. I would love some insights as to the preferred method, or any other suggestions as to how I can easily have a state for a flow not by using classes or passing the same 5 params to each task? Thank you! (class based flows:)
Copy code
class MyClass:

    @flow
    def my_instance_method(self):
        pass
n
hi @shani i would consider inverting this, meaning
@Marvin show an example of a flow that takes a complex base model subclass as a parameter. make the example concise and self contained
m
To provide you with an example, I'll need to confirm the version of Prefect you're using, as syntax and features can vary between versions. Could you let me know which version you're working with? If you're not sure, I can handle both cases for you!
n
@Marvin 3.x
m
Here's a concise, self-contained example of a Prefect 3.x flow that takes a complex Pydantic
BaseModel
subclass as a parameter. In this example, I'll demonstrate how to use a Pydantic model as a parameter for a flow. The model comprises of a simple structure with some validation rules.
Copy code
python
from prefect import flow
from pydantic import BaseModel, ValidationError

# Define a Pydantic model
class ComplexModel(BaseModel):
    a: int
    b: str

# Define a flow that accepts a ComplexModel
@flow
def flow_with_complex_model_param(model: ComplexModel):
    print(f"Received model: {model}")

if __name__ == "__main__":
    # Valid input example
    valid_model_data = {"a": 42, "b": "hello"}
    
    try:
        flow_with_complex_model_param(model=ComplexModel(**valid_model_data))
    except ValidationError as e:
        print(f"Validation Error: {e}")

    # Invalid input example
    invalid_model_data = {"a": "not_an_int", "b": "world"}
    
    try:
        flow_with_complex_model_param(model=ComplexModel(**invalid_model_data))
    except ValidationError as e:
        print(f"Validation Error: {e}")
In this example: - We use Pydantic to define a model
ComplexModel
with fields
a
and
b
. - The
flow_with_complex_model_param
flow accepts a
ComplexModel
instance as its parameter. - We demonstrate both valid and invalid data scenarios, showing Prefect's integration with Pydantic's validation capabilities, which will raise a
ValidationError
when invalid data is provided. You can test this code by running it in your local environment configured with Prefect 3.x. The example shows how Prefect's flow parameters seamlessly integrate with Pydantic models. For more details, you can refer to the Prefect 3.x documentation here.
s
@Nate Is this just data validation? I want the data to be accessible in every task of the flow
n
Is this just data validation?
not necessarily. you said
I have a lot of context that needs to pass in my flow like the logger, the account_id, and some other parameters.
so instead of the class having instance methods which invoke the flow / task, the
ComplexModel
(for example) is just a clean way to organize that context you need to pass into your flow and yes
I want the data to be accessible in every task of the flow
all standard python rules apply, so you can pass your inputs anywhere in your flow that you need, including to other tasks
Copy code
@flow
def f(inputs: ComplexModel):
  t1(inputs, ...)
  t2(inputs, ...)
s
the idea is not having to pass them over and over again
n
okay. for what it's worth I would recommend avoiding flows / tasks as instance methods, prefect is generally meant to be written functionally if you don't want to explicitly pass values (which I would recommend, since I would suggest its a design problem if explicitly passing values to functions doesn't work out) then I would use context variables, something like
s
Thanks!!