Luigi是一个上手很快的框架,用几个小时就可以学到足以应付常规多模块多任务的程序了
Luigi的安装流程如下:
pip install luigi
在Luigi中有几个核心函数,需要通过覆写实现调度:
def requires(self)
:定义当前Task运行,需要的前置Task(表示当前任务排在哪些任务之后)def run(self)
:定义当前任务触发执行的时候,执行的主要内容def output(self)
:定义当前任务输出的内容,用于判定当前Task是否正常运行,如果正常运行,则继续执行,否则在这个节点处中断
还有其他的函数用于更加个性化的逻辑:
def complete(self)
:会覆盖output的判定,用于判断Task是否运行
在python程序中,只需要把最终所需的节点传入即可:
luigi.build([RunClass()], local_scheduler=True)
线性调度示例程序
对于一个A=>B
的流程, 最后的运行程序luigi.build
只传入了RunClass()
,Luigi的框架运行流程是:
- 去看
RunClass()
的requires()
,找前置的Task,找到了PreClass()
- 去看
PreClass()
的output()
,查看前置任务是否已完成 - 如果
complete()
函数返回False
或output()
返回判定结果,判定未完成:执行前置函数的run()
;执行完成后再次检查是否完成,如果未完成则当前Task错误,中断当前调度 - 如果Task已经完成,则会返回上一级,运行
RunClass()
的output()
或complete()
查看任务是否完成 - 如果任务未完成则执行
RunClass()
的run()
,同时由于我们并未定义output()
函数,luigi没有办法确定是否完成,但是由于是最后一个节点,因此没有关系,正常退出
import luigi
class PreClass(luigi.Task): # 需要继承自luigi.Task
out_file = "pre_class.text"
def requires(self): # 所需的前置函数,也可以不写,默认为空
return []
def output(self): # 完成的依据
return luigi.LocalTarget(self.out_file) # 判断这一部分是否完成会去查看是否有out_file文件(pre_class.text)
def run(self): # 这一部分执行的主函数
print(f"运行前置的 PreClass程序")
with open(self.out_file, "a") as file:
file.write("啊哈哈哈")
class RunClass(luigi.Task):
# 这里不覆写output函数,则是默认空
def requires(self): # 所需的前置函数
return [PreClass()]
def run(self): # 这一部分执行的主函数
print(f"运行第二步 RunClass程序")
if __name__ == '__main__':
luigi.build([RunClass()], local_scheduler=True) # 只写入最后输入的数据即可
注意:
- 被前置的任务如果没有
def output(self)
或def complete(self)
函数,则运行到当前Task会报错,无法继续执行后续的任务 - 每个任务是否完成有两次判定,即:进行判定(未完成) =》运行
def run(self)
函数 =》进行判定(完成) =》运行后续的Task;如果第一次判定就完成,则不会执行当前Task的def run(self)
函数