如何用pyparsing提取HiveExecOperator顶层参数不拆分嵌套结构
问题描述
现有如下HiveExecOperator的Python调用示例代码:
fn = HiveExecOperator( task_id="abc", hql="abc.hql", dq_sql=DQCheck("pqr") .is_within_range( "COUNT(DISTINCT billing_association_type)", "type_cnts", lower=1.0, upper=float("inf"), ) .build(), dag=main_dag, )
需求是提取该函数参数列表的顶层键值对,不拆分嵌套函数、链式调用结构,比如dq_sql对应的完整DQCheck链式调用要作为单个值返回,期望输出格式如下:
[task_id="abc", hql="abc.hql", ... dq_sql=DQCheck("pqr") .is_within_range( "COUNT(DISTINCT billing_association_type)", "type_cnts", lower=1.0, upper=float("inf"), ) .build(), ...]
当前尝试的语法规则存在问题:
assignment = variable + '=' + "HiveExecOperator" + nestedExpr('(', ')').setParseAction(lambda x: print(x)) parameters.transformString(python_snippet)
错误表现:setParseAction输出的结果把嵌套的is_within_range内部的lower、upper等参数也当成顶层键值对拆分了出来,错误输出如下:
['fn', '=', 'HiveExecOperator('] ['task_id', '=', '"abc",'] ['hql', '=', '"abc.hql",'] ['dq_sql', '=', 'DQCheck("stage.billing_associations")'] ['lower', '=', '1.0,'] ['upper', '=', 'float("inf"),'] ...
解决方案
你现在的问题核心是没有区分顶层逗号和嵌套结构内的逗号,且没有把链式调用识别为完整值。按如下规则调整即可实现需求:
首先定义可以完整匹配嵌套结构、链式调用的值规则,再单独匹配顶层的键值对,调整后的代码如下:
import pyparsing as pp # 基础元素定义 string = pp.dblQuotedString() | pp.sglQuotedString() number = pp.pyparsing_common.number identifier = pp.pyparsing_common.identifier # 匹配任意层级的嵌套括号内容 nested_parens = pp.nestedExpr('(', ')') # 定义值的匹配规则:支持链式调用、多层嵌套 value = pp.Forward() # 链式调用后缀:.方法名 + 可选的参数括号 attr_call = pp.Combine('.' + identifier + pp.Optional(nested_parens)) # 基础值单元:字符串/数字/变量名/嵌套括号内容 value_atom = string | number | identifier | nested_parens # 完整值:基础单元 + 任意数量的链式调用后缀 value << pp.Combine(value_atom + pp.ZeroOrMore(attr_call), adjacent=False, joinString=' ') # 顶层参数规则:参数名 = 值 + 可选逗号 top_param = pp.Group(identifier + '=' + value + pp.Optional(',')) # 完整的HiveExecOperator调用匹配规则 hive_op_call = 'HiveExecOperator' + '(' + pp.ZeroOrMore(top_param) + ')' # 执行解析 parse_result = hive_op_call.parseString(python_snippet) # 提取顶层参数列表,过滤前后的括号标识 top_params = parse_result[2:-1] # 输出验证 for item in top_params: print(f"{item[0]}={item[2]}")
核心逻辑说明:
- 嵌套括号内的所有内容会被
nestedExpr作为整体匹配,不会拆分内部的键值对 - 链式调用的
.方法()结构会被识别为值的一部分,和前面的对象合并成单个值 - 仅顶层的
参数名=值结构会被识别为参数,嵌套结构内的赋值符不会被误判
运行后得到的top_params就是你需要的顶层键值对列表,dq_sql对应的完整DQCheck链式调用会作为单个值返回。
内容的提问来源于stack exchange,提问作者user3138594
相关产品推荐
相关产品推荐

