我无法理解如何在Luigi中制作可重复使用的任务,然后在具体情况下使用它们。
例如。我有两个通用任务对文件执行某些操作然后输出结果:
class GffFilter(luigi.Task):
"Filters a GFF file to only one feature"
feature = luigi.Parameter()
out_file = luigi.Parameter()
in_file = luigi.Parameter()
...
class BgZip(luigi.Task):
"bgZips a file"
out_file = luigi.Parameter()
in_file = luigi.Parameter()
...
现在,我想要一个首先过滤的工作流,然后使用这些任务bgzips一个特定的文件:
class FilterSomeFile(luigi.WrapperTask):
def requires(self):
return GffFilter(in_file='some.gff3', out_file='some.genes.gff3', filter='gene')
def output(self):
return self.inputs()
class BgZipSomeFile(luigi.Task):
def run(self):
filtered = FilterSomeFile()
BzZip(filtered)
但这很尴尬。在第一个任务中,我没有run
方法,我只是使用依赖项来使用通用任务。它是否正确?我应该在这里使用继承吗?
然后在第二个任务中,我无法使用依赖项,因为我需要FilterSomeFile
的输出才能使用BgZip
。但是使用动态依赖似乎是错误的,因为luigi无法构建适当的依赖图。
应该如何我从通用任务中创建Luigi工作流程?
答案 0 :(得分:0)
但这很尴尬。在第一个任务中,我没有运行方法,而我只是使用依赖项来使用通用任务。这是对的吗?
是的,根据this page,WrapperTask
是一个虚拟任务,其目的是定义任务的工作流程,因此它不会自行执行任何操作。相反,通过定义多个需求,当requires
方法中列出的每个需求都已完成时,此任务将完成。此WrapperTask
与常规Task
的主要区别在于,您不需要定义输出方法来表示此任务已成功,可以看作here。
然后在第二个任务中,我不能使用依赖项,因为我需要FilterSomeFile的输出才能使用BgZip。但是使用动态依赖似乎是错误的,因为luigi无法构建适当的依赖图。
从理论上讲,您可以使FilterSomeFile
与[{1}}具有相同的输出,使GffFilter
需要BgZipSomeFile
,然后使用FilterSomeFile
FilterSomeFile.output()
1}}访问压缩文件。但是,这个解决方案有点奇怪,因为:
包装器任务仅“运行”另一个任务,因此可以直接使用包装的任务,而无需创建BgZipSomeFile.run
。更好地使用WrapperTask
会将WrapperTask
和BgZipSomeFile
合并到FilterSomeFile
的单个子类中
正在运行方法中实例化WrapperTask
。这会产生动态依赖关系,但在此问题中不需要这样做。
最后,Task
的输入在GffFilter
任务中进行了硬编码,这使得工作流程变得不那么有用。这可以通过使FilterSomeFile
仍然接收参数,并将这些参数传递给其要求来避免。
更好的解决方案是:
WrapperClass
此代码可以在命令行中运行:
import luigi as lg
class A(lg.Task):
inFile = lg.Parameter()
outFile = lg.Parameter()
def run(self,):
with open(self.inFile, "r") as oldFile:
text = oldFile.read()
text += "*" * 10 + "\n" + "This text was added by task A.\n" + "*" * 10 + "\n"
print(text)
with open(self.outFile, "w") as newFile:
newFile.write(text)
def output(self,):
return lg.LocalTarget(self.outFile)
class B(lg.Task):
inFile = lg.Parameter()
outFile = lg.Parameter()
def run(self,):
with open(self.inFile, "r") as oldFile:
text = oldFile.read()
text += "*" * 10 + "\n" + "This text was added by task B.\n" + "*" * 10 + "\n"
with open(self.outFile, "w") as newFile:
newFile.write(text)
def output(self,):
return lg.LocalTarget(self.outFile)
class CustomWorkflow(lg.WrapperTask):
mainOutFile = lg.Parameter()
mainInFile = lg.Parameter()
tempFile = "/tmp/myTempFile.txt"
def requires(self,):
return [ A(inFile = self.mainInFile, outFile = self.tempFile),
B(inFile = self.tempFile, outFile = self.mainOutFile)
]