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

如何反序列化LazyDataframe.serialize输出的UDF并提取函数名?

解决Polars序列化UDF的反序列化与函数名提取问题

背景

Polars对LazyDataframe中的Python UDF序列化时,会经过以下流程(从源码逻辑得出):

  1. 使用pickle协议5序列化函数
  2. 用zstd级别3压缩序列化后的字节数据
  3. 将压缩结果做base64编码为字符串
  4. 最终在序列化JSON中,这个base64字符串被转换为每个字符对应的ASCII十进制数字数组

解决方案

前置依赖

先安装zstd库用于解压:

pip install zstd

方法一:直接反序列化提取函数名(信任数据源时使用)

如果确定UDF来源安全,可以直接反序列化得到函数对象后提取名称:

import pickle
import base64
import zstd

# 替换为你从JSON中拿到的UDF数字数组
udf_num_array = [128, 5, 149, 198, 1, ..., 134, 82, 48, 46]

# 1. 将数字数组还原为base64字符串
base64_str = ''.join(chr(num) for num in udf_num_array)
# 2. base64解码获取zstd压缩字节
compressed_bytes = base64.b64decode(base64_str)
# 3. zstd解压得到pickle序列化的原始字节
pickle_bytes = zstd.decompress(compressed_bytes)
# 4. 反序列化得到函数对象并提取名称
func = pickle.loads(pickle_bytes)
print(func.__name__)  # 输出示例:multiplyBy2

方法二:解析pickle字节提取函数名(安全优先,无需反序列化函数)

如果担心未知pickle数据的安全风险,可以直接解析pickle字节结构提取函数名,避免执行函数代码:

import base64
import zstd

# 替换为你从JSON中拿到的UDF数字数组
udf_num_array = [128, 5, 149, 198, 1, ..., 134, 82, 48, 46]

# 先还原出pickle字节数据
base64_str = ''.join(chr(num) for num in udf_num_array)
compressed_bytes = base64.b64decode(base64_str)
pickle_bytes = zstd.decompress(compressed_bytes)

# 解析pickle结构提取函数名
# 函数引用的pickle结构中,第二个\x8c标记后跟着函数名的长度与名称
parts = pickle_bytes.split(b'\x8c')
if len(parts) >= 3:
    func_name_length = parts[2][0]
    func_name = parts[2][1:1+func_name_length].decode('utf-8')
    print(func_name)  # 输出示例:multiplyBy2

关键说明

  • 两种方法都无需将整个序列化JSON反序列化为LazyDataframe,仅针对UDF的数字数组处理即可
  • 方法二通过解析pickle字节结构实现,避免了反序列化可能带来的安全风险,更适合处理不可信来源的数据

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 10:52:23