Passing runtime arguments via the functional API a...
# ask-community
t
Passing runtime arguments via the functional API at task instantiation
Hi all, I am finding the Prefect API a little confusing / indirect with how Tasks are instantiated. Referring to the
PostgresExecute
Task, I see that there are a number of kwargs that we can set upon instantiation (e.g.
db_name
,
host
etc). However, the
password
is not set until runtime. Referring to my simple example below, how are we expected to pass in the password?
Copy code
with Flow("setup") as flow:
    task1 = PostgresExecute(
        name="task_name",
        db_name="abc,
        user="peter,
        host="my_host",
        port=5432,
        query="INSERT INTO blah blah"
        # Cannot set the password at intantiation of the task, as it isn't an arg in __init__
    )
Ah... I needed to run
task1.bind(password=password)
What's the reason for this approach to certain arguments vs setting them at task instantiation?
I'm also getting this message, but again, finding the docs / concept a bit elusive. So any guidance much appreciated 🙂
Tasks were created but not added to the flow: {<Task: lists all tasks>,.
This can occur when
Task
classes, including
Parameters
, are instantiated inside a
with flow:
block but not added to the flow either explicitly or as the input to another task.
That second question / warning message doesn't seem to break anything. The Flow still runs
a
@Todd de Quincey can you share your entire example Flow so that I could reproduce and give more info? Overall: • when it comes to tasks from the task library, they typically need to be instantiated first and assigned to a task variable - this creates a task which you can call in your Flow constructor, as if it were a normal @task function task, see this example: https://gist.github.com/fc29ea1e02113d6a6b20cbaa03ac315e • when you use Parameters in your Flow, but you don’t pass their value to any downstream tasks, this only initializes the Parameter task - this causes the warnings you shared. The best solution is to use this Parameter value in a downstream task, or alternatively to add those instantiated parameters to the flow, you could use flow.add_task():
Copy code
from prefect import Flow, Parameter

name_of_the_parameter_task = Parameter("result_basepath", default="~")

with Flow('Parameterized Flow') as flow:
	...
flow.add_task(name_of_the_parameter_task)
k
In general, we want to move in a direction where all of the Task is the Task Library are runtime configurable. You are right that this specific one is not. There was this PR that I guess did not go through. But you can check the edits he made and make your own version of the Postgres Task by subclassing it. And then for tasks in the task library, you can do:
Copy code
pgtask = PostgresExecute(...)

with Flow("setup") as flow:
    pgtask(...)
or
Copy code
with Flow("setup") as flow:
    x = PostgresExecute(init_here)(run_here)
t
Ah. Gotcha, @Kevin Kho. So in your second example, we expected in our Flow file to then call the run method on the Task outside of the context manager to pass in the runtime arg? Is there any benefit to this approach vs calling a Task.bind from within the context manager? Note, for my use case I don’t want to be able to change the args for this task at runtime. I presume calling run on the task outside of the context manager will allow us to pass in Params from the flow run?
@Anna Geller I’ll ping across my example to you shortly :)
Side note, you both do a wonderful job here in the forums! Amazing work.
🙏 2
âž• 1
a
I think there are no particular benefits using one way or another. The
bind
method is strictly tied to the imperative API (where tasks are defined as classes rather than functions), but subjectively, just passing the arguments as data dependency seems much easier to understand and more natural - see here line 19 https://gist.github.com/anna-geller/fc29ea1e02113d6a6b20cbaa03ac315e#file-postgres_task_example-py-L19
k
The second example will already call the task. No need to call the run explicitly.
t
Thanks, Anna. I see what you mean. I’m trying to “Airflow-ify” Prefect, whereby you call the class inside the flow. Makes a lot more sense now. Thanks both for your time :)
👍 1