Databricks自定义Python UDF报错:charMonth变量未赋值
问题
在Databricks/Python环境中,尝试创建自定义UDF CreateBloombergSymbol,将日期字符串pctym的月份转换为彭博对应字符符号,但运行时抛出错误:UnboundLocalError: local variable 'charMonth' referenced before assignment。
函数定义代码:
from pyspark.sql.functions import col, substr def CreateBloombergSymbol(pctym): digitMonth = pctym[6:2:1] match digitMonth: case "01": charMonth = "F" case "02": charMonth = "G" case "03": charMonth = "H" case "04": charMonth = "J" case "05": charMonth = "K" case "06": charMonth = "M" case "07": charMonth = "N" case "08": charMonth = "Q" case "09": charMonth = "U" case "10": charMonth = "V" case "11": charMonth = "X" case "12": charMonth = "Z" return charMonth
注册并调用UDF代码:
varMyBloombergFunction = spark.udf.register("CreateBloombergSymbol", CreateBloombergSymbol) from pyspark.sql.functions import col dfPos.select( col('*'), varMyBloombergFunction(col('pctym')).alias('mynewcolFuncBB') ).display()
问题原因
- 未覆盖所有分支:
match语句只处理了01-12的月份值,当digitMonth是其他值时,charMonth从未被赋值,但函数最后直接返回该变量,触发未绑定局部变量的错误。 - 切片逻辑错误:
pctym[6:2:1]不符合Python切片规则(格式为[起始索引:结束索引:步长]),如果日期字符串是YYYYMMDD格式,正确提取月份的写法应该是pctym[4:6],当前写法会得到空字符串或错误子串,这也是导致digitMonth不匹配任何case的常见原因。
修复方案
方案1:完善match分支,添加默认处理
给match语句增加默认分支,处理所有非预期的月份值:
from pyspark.sql.functions import col, substr def CreateBloombergSymbol(pctym): # 修正切片逻辑,提取YYYYMMDD格式中的月份部分 digitMonth = pctym[4:6] match digitMonth: case "01": charMonth = "F" case "02": charMonth = "G" case "03": charMonth = "H" case "04": charMonth = "J" case "05": charMonth = "K" case "06": charMonth = "M" case "07": charMonth = "N" case "08": charMonth = "Q" case "09": charMonth = "U" case "10": charMonth = "V" case "11": charMonth = "X" case "12": charMonth = "Z" case _: # 处理所有非预期情况 charMonth = "" # 也可返回"INVALID"等标记值 return charMonth
方案2:用字典映射替代match(更简洁)
用字典存储月份与彭博符号的对应关系,通过get方法自动处理默认情况:
from pyspark.sql.functions import col, substr def CreateBloombergSymbol(pctym): # 修正切片逻辑 digitMonth = pctym[4:6] month_map = { "01": "F", "02": "G", "03": "H", "04": "J", "05": "K", "06": "M", "07": "N", "08": "Q", "09": "U", "10": "V", "11": "X", "12": "Z" } # 不存在对应值时返回空字符串 return month_map.get(digitMonth, "")
额外建议:增加格式校验
如果pctym可能存在非标准日期格式,可在函数开头添加校验:
def CreateBloombergSymbol(pctym): # 校验日期字符串长度是否符合YYYYMMDD格式 if len(pctym) != 8: return "" digitMonth = pctym[4:6] month_map = { "01": "F", "02": "G", "03": "H", "04": "J", "05": "K", "06": "M", "07": "N", "08": "Q", "09": "U", "10": "V", "11": "X", "12": "Z" } return month_map.get(digitMonth, "")
内容的提问来源于stack exchange,提问作者solarissf
相关产品推荐
相关产品推荐

