You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中如何将YAML中的Lambda字符串转为可调用对象传入Deequ校验方法

如何将YAML中的Lambda字符串转为可调用对象传入Deequ校验?

我在用Deequ做数据校验,为提升易用性,编写了遍历YAML配置自动添加校验的代码:

for exp in checks[table]:
    params = checks[table][exp]
    validate = getattr(check, exp)
    result = result.addCheck(
        validate(*params)
    )

对应的YAML配置如下:

checks = """
table:
  hasSize:
   - "lambda x: x < 55000"
  isUnique: 
   - "customer"
"""

但YAML中的"lambda x: x < 55000"会被识别为字符串,调用校验时触发错误:

Can't execute the assertion: An exception was raised by the Python Proxy. Return Message: Traceback (most recent call last):   File "/databricks/spark/python/lib/py4j-0.10.9-src.zip/py4j/java_gateway.py", line 2442, in _call_proxy     return_value = getattr(self.pool[obj_id], method)(*params)   File "/databricks/python/lib/python3.8/site-packages/pydeequ/scala_utils.py", line 37, in apply     return self.lambda_function(arg) TypeError: 'str' object is not callable !

需要将该Lambda字符串转换为可调用对象后传入校验函数,以下是几种可行方案:


解决方案

方法1:使用eval直接转换(简单但需注意安全)

eval可直接将字符串形式的Lambda转为可调用对象,修改循环代码添加判断逻辑:

import re

# 匹配Lambda格式字符串的正则
lambda_pattern = re.compile(r'^lambda\s+.+:')

for exp in checks[table]:
    params = checks[table][exp]
    processed_params = []
    for param in params:
        # 判断是否为Lambda字符串
        if isinstance(param, str) and lambda_pattern.match(param):
            processed_params.append(eval(param))
        else:
            processed_params.append(param)
    
    validate = getattr(check, exp)
    result = result.addCheck(
        validate(*processed_params)
    )

注意:eval存在安全风险,若YAML配置来自不可信渠道,请勿使用此方法,防止恶意代码注入。

方法2:用ast模块安全解析Lambda表达式

ast模块可先验证表达式合法性再解析,比直接用eval更安全:

import ast

for exp in checks[table]:
    params = checks[table][exp]
    processed_params = []
    for param in params:
        if isinstance(param, str) and param.strip().startswith('lambda'):
            # 解析表达式
            expr = ast.parse(param, mode='eval')
            # 确保解析结果是Lambda表达式
            if isinstance(expr.body, ast.Lambda):
                processed_params.append(eval(compile(expr, '<string>', 'eval')))
            else:
                processed_params.append(param)
        else:
            processed_params.append(param)
    
    validate = getattr(check, exp)
    result = result.addCheck(
        validate(*processed_params)
    )

方法3:自定义YAML标记区分Lambda参数

在YAML中给Lambda参数添加自定义标记,解析时自动转换:
修改后的YAML配置:

checks = """
table:
  hasSize:
   - !lambda "x: x < 55000"
  isUnique: 
   - "customer"
"""

解析YAML时注册自定义构造器:

import yaml

# 自定义Lambda构造器
def lambda_constructor(loader, node):
    lambda_body = loader.construct_scalar(node)
    return eval(f'lambda {lambda_body}')

# 注册构造器
yaml.add_constructor('!lambda', lambda_constructor)

# 解析YAML(checks_yaml_str为原始YAML字符串)
checks = yaml.load(checks_yaml_str, Loader=yaml.FullLoader)

之后循环代码无需额外处理,可直接使用参数。


内容的提问来源于stack exchange,提问作者Jakobkubek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 18:30:34