Adrien Besnard
03/14/2025, 8:25 PMSource
class (which has a refresh()
method) that I want both to be able to call through a CLI and within Prefect. Does it make sense to do something like this?
class Source():
def refresh(self):
self.extract
self.load()
self.transform()
@task()
def extract(self):
...
@task()
def load(self):
...
@task()
def tranform(self):
...
@flow
def refresh_source():
source = Source()
source.load()
This way, I'm able to instanciate an instance of the Source
class elsewhere without relying on Prefect. But in the meantime, I find weird to "infect" everything using @task
. What do you think?Nate
03/14/2025, 8:46 PMclass Source:...
@task
def extract(): ...
@task
def load(): ...
@task
def transform(): ...
@flow
def refresh_source(source: Source):
extract(...)
load(...)
transform(...)
that way (if you want) you can define modular (prefect-unaware) logic elsewhere and call it from the prefect tasks, where Source
is just a serializable / portable dataclass
one reason I'd recommend this is because a nice advantage of tasks is cache policies and you'd have to explicitly omit self
from consideration (as far as computing cache keys) if your tasks are instance methods, and then there's our somewhat subjective preference for functional style 🙂
but if you are stuck with the class Source
paradigm, I'd just define something that looks like
@flow
def refresh_source(source: Source):
and call that from within Source.refresh
- I just wouldn't recommend decorating instance methods if you can help itAdrien Besnard
03/14/2025, 9:22 PMAdrien Besnard
03/14/2025, 9:23 PMNate
03/14/2025, 9:24 PMOnce within a classic function (let's say a @click.command())why not just call the flow you already wrote here?
Adrien Besnard
03/14/2025, 9:29 PMAdrien Besnard
03/14/2025, 9:30 PMNate
03/14/2025, 9:30 PM» ipython
#[1]
from prefect import flow
#[2]
@flow
def foo(): print('hi no prefect pls')
#[3]
foo.fn()
hi no prefect pls
Nate
03/14/2025, 9:30 PMAdrien Besnard
03/14/2025, 9:32 PMNate
03/14/2025, 9:33 PM@flow
def public_foo():
_private_foo()
but i think that's a situational preference thing (i personally don't like arbitrary extra wrapping unless we really need it)Adrien Besnard
03/14/2025, 9:35 PMAdrien Besnard
03/14/2025, 9:35 PMNate
03/14/2025, 9:36 PMAdrien Besnard
03/14/2025, 9:37 PMNate
03/14/2025, 9:42 PMfoo
that has (normal non-prefect) functions inside which you'd want to "be tasks" when you want foo
to run as a flow, but since
> none of our flows have tasks because the logic is already embedded in the other packages
those task definitions don't exist yetAdrien Besnard
03/14/2025, 9:43 PMAdrien Besnard
03/14/2025, 9:44 PMAdrien Besnard
03/14/2025, 9:45 PMAdrien Besnard
03/14/2025, 9:48 PMAdrien Besnard
03/14/2025, 9:52 PMNate
03/14/2025, 10:03 PM