ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Luigi 参数系统完全指南:从 Parameter 定义到命令行与配置解析

Luigi 参数系统完全指南:从 Parameter 定义到命令行与配置解析 Luigi 参数系统完全指南从 Parameter 定义到命令行与配置解析【免费下载链接】luigiLuigi is a Python module that helps you build complex pipelines of batch jobs. It handles dependency resolution, workflow management, visualization etc. It also comes with Hadoop support built in.项目地址: https://gitcode.com/gh_mirrors/lu/luigiParameters 是 Luigi 任务Task参数化的核心机制相当于为每个 Task 自动生成构造函数。本文围绕 doc/parameters.rst 展开系统讲解如何在类作用域声明参数、Luigi 如何接管构造与命令行解析的样板代码并深入分析实例缓存、显著/非显著参数、参数可见性、内置参数类型、跨类参数注入、配置覆盖以及参数解析优先级等关键主题最后结合 luigi/parameter.py 与 luigi/task.py 的源码实现给出可复制、可运行的实战示例。读完本文你将能够熟练地为任务声明参数、在命令行与配置文件中注入参数值并理解任务签名task_id的构成原理。Parameters 是什么任务的“构造函数”在 Luigi 中Parameters 是每个 Task 的“构造函数等价物”。Luigi 要求你在类作用域中通过实例化luigi.parameter.Parameter对象来声明参数import datetime import luigi class DailyReport(luigi.contrib.hadoop.JobTask): date luigi.DateParameter(defaultdatetime.date.today()) # ... 其余任务逻辑通过这种声明式写法Luigi 可以替你处理所有原本需要手工写在构造函数里的样板代码。声明之后在 Python 中可以直接用DailyReport(datetime.date(2012, 5, 10))或DailyReport()构造对象Luigi 会自动创建一个命令行解析器负责把字符串转换成对应的 Python 类型在命令行上可以这样运行任务luigi DailyReport --date 2012-05-10字符串2012-05-10会被自动解析为datetime.date对象。参数值会被设置到 Task 对象实例上例如d DailyReport(datetime.date(2012, 5, 10)) print(d.date) # 2012-05-10与构造时传入的日期一致命令行方式运行任务时同样如此实例上的date属性就是解析后的日期对象。从源码上看这一机制的核心实现位于 luigi/task.py 的Task.__init__它通过get_param_values收集参数值然后逐个setattr到实例上并基于参数生成task_id。而命令行解析则在 luigi/cmdline_parser.py 的CmdlineParser中完成它借助argparse为每个已注册参数生成--参数名形式的 flag并根据参数类型调用对应的parse方法完成类型转换。实例缓存相同签名的任务是同一个实例任务由“类名 参数值”唯一标识。在同一 worker 内同类的两个任务如果参数值相同它们不仅是相等的而且是同一个实例is为True import luigi import datetime class DateTask(luigi.Task): ... date luigi.DateParameter() ... a datetime.date(2014, 1, 21) b datetime.date(2014, 1, 21) a is b False # 普通 Python 对象并不共享 c DateTask(datea) d DateTask(dateb) c DateTask(date2014-01-21) d DateTask(date2014-01-21) c is d True # Luigi 任务实例被缓存复用这种“同一签名同一实例”的行为是 Luigi 依赖图去重的基础调度器与 worker 可以据此避免对相同任务重复执行。其底层支撑是 luigi/task.py 中的task_id计算——task_id task_id_str(get_task_family(), to_str_params(only_significantTrue, only_publicTrue))而__hash__直接使用hash(self.task_id)luigi/task.py__eq__也比较task_idluigi/task.py。非显著参数significantFalse不影响签名但影响实例如果一个参数以significantFalse创建它在任务签名中会被忽略。两个任务若只在非显著参数上不同它们的签名相同但不是同一个实例 class DateTask2(DateTask): ... other luigi.Parameter(significantFalse) ... c DateTask2(datea, otherfoo) d DateTask2(dateb, otherbar) c DateTask2(date2014-01-21) # repr 中不显示 other d DateTask2(date2014-01-21) c.other foo # 值仍然各自保留 d.other bar c is d False # 不是同一个实例 hash(c) hash(d) True # 但哈希相同非显著参数的典型用途包括密码、token 等敏感信息——它们不应参与任务标识也不应通过调度器对外暴露。这一点在 luigi/parameter.py 的Parameter.__init__文档字符串中有明确说明同时 luigi/task.py 的get_param_names和 luigi/task.py 的to_str_params都按significant过滤参与签名的参数。参数可见性ParameterVisibility借助luigi.parameter.ParameterVisibilityluigi/parameter.py一个IntEnumPUBLIC0、HIDDEN1、PRIVATE2你可以配置参数的可见性。默认所有参数都是 public也可以设为 hidden 或 private import luigi from luigi.parameter import ParameterVisibility luigi.Parameter(visibilityParameterVisibility.PRIVATE)三种可见性的语义可见性说明ParameterVisibility.PUBLIC默认处处可见ParameterVisibility.HIDDEN在 Web 视图中被忽略但如果开启了 db_history 保存仍会写入数据库ParameterVisibility.PRIVATE仅任务内部可见可见性影响参数对外暴露的范围任务 ID 与对外序列化只包含 public 参数。从源码看luigi/task.py 的_get_param_visibilities会排除PRIVATE参数to_str_paramsluigi/task.py在only_public模式下也过滤非 public 参数。当构造器收到非法可见性值时luigi/parameter.py 会回退到PUBLIC。相应的行为验证可见于 test/scheduler_parameter_visibilities_test.py。参数类型用 Parameter 子类驱动类型转换上面的例子中参数“类型”由不同的Parameter子类决定。Luigi 内置了一批常用子类例如DateParameter、DateIntervalParameter、IntParameter、FloatParameter等全部定义在 luigi/parameter.py。Python 不是静态类型语言你不需要为参数指定类型直接用基类Parameter值为字符串即可。之所以使用DateParameter这样的子类是因为 Luigi 需要在命令行交互中知道类型——它据此把命令行传入的字符串转换成对应类型例如把2012-05-10转成datetime.date而不是保留字符串。每个子类的核心是重写parse字符串→值与serialize值→字符串两个方法见 luigi/parameter.py。下表汇总了仓库中主要的参数类型及命令行输入格式参数类Python 值类型命令行示例Parameterstr--x fooDateParameterdatetime.date格式%Y-%m-%d--date 2013-07-10MonthParameterdatetime.date月初格式%Y-%m--month 2013-07YearParameterdatetime.date年初格式%Y--year 2013DateHourParameterdatetime.datetimeISO 8601 到小时--dt 2013-07-10T19DateMinuteParameterdatetime.datetime到分钟--dt 2013-07-10T1907DateSecondParameterdatetime.datetime到秒--dt 2013-07-10T190738DateIntervalParameterluigi.date_interval.DateInterval--interval 2015-11-04、--interval 2015-05、--interval 2015-W35、--interval 2015-11-04-2015-12-04IntParameterint--num 42FloatParameterfloat--ratio 0.5BoolParameterbool--flag隐式或--flag true显式TimeDeltaParameterdatetime.timedelta--td 1 week 2 days、--td P1DT1H、--td 3600TaskParameter任务类--task my_namespace.MyTaskEnumParameterenum.Enum成员--model HondaEnumListParameter枚举成员元组--model Honda,VolvoListParameter元组从 JSON 数组解析--grades [100,70]DictParameterFrozenOrderedDict从 JSON 对象解析--tags {role: web, env: staging}TupleParametertuple/ 元组的元组--loc ((12,3),(4,15))NumericalParameter指定类型的数值含范围校验--my-param-1 -3ChoiceParameter/ChoiceListParameter限定选项的值--my-param 0.1/--my-param foo,barPathParameterpathlib.Path--path /data/file.txtOptionalParameter等Optional*系列允许None空串解析为None--opt 几个值得注意的细节日期参数的 interval 归一化DateParameter、MonthParameter、YearParameter以及_DatetimeParameterBase系列的normalize会把值“钳制”到以start默认 Unix 纪元为起点的每个interval上luigi/parameter.py、luigi/parameter.py、luigi/parameter.py、luigi/parameter.py这对按天/月/年聚合批处理非常有用。BoolParameter 的两种解析模式默认隐式解析--the-bool-parameter出现即为True不出现为False默认值False也可按参数或全局设置为显式解析--the-bool-parameter true|falseluigi/parameter.py。List/Dict 参数可带 JSON Schema 校验ListParameter与DictParameter接受schema参数原生 dict 或jsonschema验证器实例不合法值会在解析/归一化阶段直接抛错luigi/parameter.py、luigi/parameter.py。依赖jsonschema包未安装时会降级并发出警告。TupleParameter 兼容两种输入既接受 JSON 数组形式[[1,2],[3,4]]也接受 Python 字面量形式((1,2),(3,4))luigi/parameter.py。PathParameter提供absolute与exists两个开关existsTrue时路径不存在会抛出ValueError值被归一化为pathlib.Pathluigi/parameter.py。为其他类设置参数值跨类注入所有参数也都会暴露在类级别的命令行界面上。例如有 TaskA 和 TaskBclass TaskA(luigi.Task): x luigi.Parameter() class TaskB(luigi.Task): y luigi.Parameter()你可以运行luigi TaskB --y 42来执行 TaskB同时也可以运行luigi TaskB --y 42 --TaskA-x 43把TaskA.x的类级值设为 43。在 Python 中仍然可以通过TaskA(x44)实例化来覆盖它。跨类参数注入的底层机制在 luigi/cmdline_parser.py解析器为每个已注册参数生成全局 flag--TaskA-x形式同时仅为根任务生成局部 flag--x形式。flag 名由下划线转为连字符task_name _ param_name→--task-name-param-name任务家族名的连字符分隔规则与此对应。所有参数也都可以从配置文件设置。例如在 cfg 配置文件中[TaskA] x: 45与命令行一样这会把TaskA.x的类级值设为 45Python 中实例化TaskA(x44)仍然可以覆盖。参数从配置摄入ParamConfigIngestion的完整机制见 doc/configuration.rst配置类luigi.Config的写法也基于同一套摄入规则可以参考 examples/config.toml 中的实际示例。参数解析优先级参数的取值按以下优先级从高到低解析构造器传入的值或命令行上的任务级值作用于实例级别命令行上的值作用于类级别配置文件中的选项作用于类级别参数提供的默认值作用于类级别。例如TaskA.x的最终值会优先取实例构造时的TaskA(x44)其次命令行--TaskA-x 43再次配置文件[TaskA] x: 45最后才是Parameter(default...)中的默认值。这一优先级在 luigi/parameter.py 的_get_value/_value_iterator中按序实现先检查命令行解析器CmdlineParser中的全局参数再查配置[task_name] param_name随后是已废弃的config_path兼容逻辑最后返回_default。Task.__init__通过get_param_valuesluigi/task.py把这一过程落地先填位置参数、再填关键字参数、最后对未提供的参数走“命令行→配置→默认值”的解析链若最终仍无值会抛出MissingParameterExceptionluigi/parameter.py。实战小结声明参数用类作用域上的Parameter子类Luigi 自动生成构造函数与命令行解析相同类名 相同显著参数值的任务在 worker 内是同一实例任务签名由task_id唯一标识significantFalse让参数不参与签名适合敏感信息visibility控制参数对外暴露程度命令行用--param value根任务或--TaskName-param value其他类传值配置文件用[TaskName] param: value传值取值优先级恒为构造参数 命令行 配置文件 默认值需要更多类型转换、区间钳制或 JSON Schema 校验时优先选用IntParameter、DateParameter、NumericalParameter、ListParameter、DictParameter等内置子类必要时可自定义子类重写parse/serialize/normalize。相关源码与测试参数实现位于 luigi/parameter.py任务侧整合位于 luigi/task.py命令行解析位于 luigi/cmdline_parser.py类型化参数的完整行为验证可参考 test/parameter_test.py、test/date_parameter_test.py、test/numerical_parameter_test.py、test/list_parameter_test.py、test/dict_parameter_test.py 与 test/choice_parameter_test.py。【免费下载链接】luigiLuigi is a Python module that helps you build complex pipelines of batch jobs. It handles dependency resolution, workflow management, visualization etc. It also comes with Hadoop support built in.项目地址: https://gitcode.com/gh_mirrors/lu/luigi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表