繁体   English   中英

在Luigi中重用通用任务

[英]Re-using generic tasks in Luigi

我在理解如何在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()
    ...

现在,我想要一个工作流程,该工作流程首先过滤,然后使用以下任务bgzip特定文件:

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无法构建适当的依赖关系图。

应该怎样做一个路易吉工作流出来的我一般任务?

但这很尴尬。 在第一个任务中,我没有运行方法,而我只是在使用依赖项来使用通用任务。 这个对吗?

是的,根据此页面WrapperTask是一个虚拟任务,其目的是定义任务的工作流程,因此它本身不会执行任何操作。 相反,通过定义几个需求,当requires方法中列出的每个需求都已完成时,此任务将完成。 本的主要区别WrapperTask到正规的Task ,就是你不需要定义输出方法,发出信号,这个任务suceeded,可以看出这里

然后在第二个任务中,我不能使用依赖项,因为我需要FilterSomeFile的输出才能使用BgZip。 但是使用动态依赖关系似乎是错误的,因为luigi无法构建适当的依赖关系图。

从理论上说,你可以把FilterSomeFile有输出相同GffFilter ,使BgZipSomeFile需要FilterSomeFile ,然后用FilterSomeFile.output()BgZipSomeFile.run访问的压缩文件。 但是,此解决方案有些奇怪,因为:

  • 包装器任务仅“运行”另外一个任务,因此包装后的任务可以直接使用,而无需创建WrapperTask 有一种更好的使用WrapperTask将涉及合并BgZipSomeFileFilterSomeFile在一个子类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)
                ]

可以使用以下命令在命令行中运行此代码:

PYTHONPATH='.' luigi --module pythonModuleContainingTheTasks --local-scheduler CustomWorkflow --mainInFile ./text.txt --mainOutFile ./procText.txt

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM