Multiple targets
The previous example showed how to use the prism.decorators.target
decorator to define a single target. Prism also supports multiple targets in a single task. There are two ways that this can be done:
Multiple
prism.decorators.target
callsUsing
prism.decorators.target_iterator
Multiple prism.decorators.target
prism.decorators.target
Building off of the previous example, let's say you want your HelloWorld
task to also produce a file with the string "foo, bar"
. You can do that as follows:
# tasks/hello_world.py
import prism.task
import prism.target
import prism.decorators
class HelloWorld(prism.task.PrismTask):
@prism.decorators.target(type=prism.target.Txt, loc="/Users/hello_world.txt")
@prism.decorators.target(type=prism.target.Txt, loc="/Users/foo_bar.txt")
def run(self, tasks, hooks):
test_str1 = "Hello, world!"
test_str2 = "foo, bar"
return test_str, test_str2
In this revised task, the objects (i.e., the strings) corresponding to the different targets are returned as a tuple, and for every returned object in the tuple there is a prism.decorators.target
call.
That's it! That's all you have to do to specify multiple targets. Now, tasks.ref("hello_world.py")
will return a tuple of the target paths:
# tasks/second_task.py
import prism.task
import prism.target
import prism.decorators
class SecondTask(prism.task.PrismTask):
def run(self, tasks, hooks):
tasks.ref("hello_world") # returns ("/Users/hello_world.txt", "/Users/foo_bar.txt")
prism.decorators.target_iterator
prism.decorators.target_iterator
Using multiple prism.decorators.target
calls can be tedious if you need to save a dozen or more targets at a time. That's where prism.decorators.target_iterator
comes in.
Here's how to use it. Let's say you have data from different clients stored in different CSVs and you want to apply the same processing to all of them.
# tasks/process_client_data.py
import prism.task
import prism.target
import prism.decorators
import prism_project
import pandas as pd
class ProcessClientData(prism.task.PrismTask):
@prism.decorators.target_iterator(
type=prism.target.PandasCsv, loc="/Users/"
)
def run(self, tasks, hooks):
results_dict = {}
clients = ['clientA', 'clientB', 'clientC', 'clientD']
for cl in clients:
df = pd.read_csv(f'{cl}.csv')
df_processed = ... # do some processing here
results_dict[f'{cl}_processed.csv'] = df_processed
return results_dict
Here's what's happening under the hood:
We iterate through the different clients, process their data, and store the processed data in a dictionary (
results_dict
). This dictionary uses the desired target file name as keys and the objects as values.The task function returns the
results_dict
. Prism then iterates through the key, value pairs in the dictionary and saves each value (i.e., each object) to the path{loc}/{key}
.
In other words, the task above will save four targets:
/Users/clientA_processed.csv
/Users/clientB_processed.csv
/Users/clientC_processed.csv
/Users/clientD_processed.csv
Now, tasks.ref("process_client_data.py")
will return the base loc
path in which all the targets were saved (i.e., "/Users/"
):
# tasks/second_task.py
import prism.task
import prism.target
import prism.decorators
class SecondTask(prism.task.PrismTask):
def run(self, tasks, hooks):
tasks.ref("process_client_data") # returns "/Users/"
Check out the API reference documentation for more information.