Reputation: 3412
With Python doit I want to generate sub-tasks by reading a list of files from a file (that was generated in an earlier task), then yield
ing actions for each of those files:
def task_generates_list_of_files():
def generate_file():
with open('list_of_files.txt', 'w') as fo:
for x in range(20):
fo.write(f'thing_{x}.txt\n')
return {
'actions': [generate_file],
'targets': ['list_of_files.txt']
}
def task_generate_subtasks_using_file():
with open('list_of_files.txt', 'r') as fo:
for filename in fo:
filename = filename.strip()
yield {
'name': filename,
'actions': [f'program_to_run {filename}'],
'file_dep': ['list_of_files.txt']
}
However, because list_of_files.txt
doesn't exist when the tasks are being set up by doit, it raises a FileNotFoundError
exception.
I have seen this answer but am not clear that getargs
can work when generating subtasks, because I wouldn't be able to loop through the list of files until they were injected into a Python action, at which point I can't yield any sub-tasks. Doing that results in:
Python Task error:...
It must return:
False for failed task.
True, None, string or dict for successful task
returned <generator object...
Upvotes: 2
Views: 1372
Reputation: 3412
In the end, I'd missed something I hadn't seen before in the doit documentation: delayed tasks. You can use create_after
to defer creation of a task until after a given task is executed.
In my case this allows list_of_files.txt
to be generated by task_generates_list_of_files
before list_of_files.txt
is read within the task definition of task_generate_subtasks_using_file
:
from doit import create_after
# Show output
DOIT_CONFIG = {
'verbosity': 2
}
def task_generates_list_of_files():
def generate_file():
with open('list_of_files.txt', 'w') as fo:
for x in range(20):
fo.write(f'thing_{x}.txt\n')
return {
'actions': [generate_file],
'targets': ['list_of_files.txt']
}
@create_after('generates_list_of_files')
def task_generate_subtasks_using_file():
with open('list_of_files.txt', 'r') as fo:
for filename in fo:
filename = filename.strip()
yield {
'name': filename,
'actions': [f'echo {filename}'],
'file_dep': ['list_of_files.txt']
}
Upvotes: 1