如何通过Python pyrfc正确读取SAP BW InfoCube数据?
SAP BW InfoCube数据读取解析问题解决方案
问题描述
通过Python的pyrfc库调用ABAP函数RSDRI_INFOPROV_READ_RFC读取SAP BW InfoCube数据时,返回的E_T_RFCDATA字段存在格式混乱问题:字段顺序错乱、KPI数值丢失、乱码。SAP系统内需用RSDRI_DATA_UNWRAP结构化数据,但该函数非RFC函数无法远程调用,需Python端等价解析方案。
现有代码
import pyrfc import pandas as pd import pprint from pyrfc import Connection, ABAPApplicationError, ABAPRuntimeError, LogonError, CommunicationError ASHOST = "myashost" SYSNR = "xx" CLIENT = 'xx' USER = "my_user" PASSWD = "mymdp" lang= 'EN' i_th_sfc = [ {"CHANM": "/CPMB/WVDU6SJ", "CHAALIAS": "AUDITTRAIL", }, {"CHANM": "/CPMB/WVD9OS5", "CHAALIAS": "TIME", }, {"CHANM": "/CPMB/WVD9X7E", "CHAALIAS": "CONTRIBUTOR", }, {"CHANM": "/CPMB/WVDYXDT", "CHAALIAS": "RUBRIC", } ] i_th_sfk = [ {"KYFNM": "/CPMB/SDATA", "KYFALIAS" : "KPI", "AGGR" : "SUM" }, ] conn = pyrfc.Connection(ashost=ASHOST, sysnr=SYSNR, client=CLIENT, user=USER, passwd=PASSWD, lang= lang) result = conn.call("RSDRI_INFOPROV_READ_RFC", I_INFOPROV = "/CPMB/WVIKBIP" ,I_T_SFC = i_th_sfc ,I_T_SFK = i_th_sfk , I_MAXROWS = 2 ) pprint.pprint(result, width=100, compact=True)
解决方案
1. 理解E_T_RFCDATA结构
RSDRI_INFOPROV_READ_RFC返回的E_T_RFCDATA是扁平化字节流,每行数据按传入的特征(I_T_SFC)和关键值(I_T_SFK)定义顺序拼接,需根据字段长度、数据类型拆分解析。
2. Python端实现解析逻辑
步骤1:获取字段元数据
调用RSDRI_INFOPROV_METADATA_READ_RFC获取字段长度、类型等元数据,无需手动计算:
# 获取InfoCube元数据 metadata = conn.call("RSDRI_INFOPROV_METADATA_READ_RFC", I_INFOPROV="/CPMB/WVIKBIP", I_T_SFC=i_th_sfc, I_T_SFK=i_th_sfk ) # 提取特征和关键值的元数据 sfc_metadata = metadata["E_T_SFC"] sfk_metadata = metadata["E_T_SFK"]
步骤2:整理字段规则
按特征、关键值的顺序,整理每个字段的别名、长度和类型:
field_specs = [] # 添加特征字段规则 for field in sfc_metadata: field_specs.append({ "name": field["CHAALIAS"], "length": field["INTLEN"], "type": field["INTTYPE"] }) # 添加关键值字段规则 for field in sfk_metadata: field_specs.append({ "name": field["KYFALIAS"], "length": field["INTLEN"], "type": field["INTTYPE"] })
步骤3:拆分并转换数据
遍历E_T_RFCDATA的每行数据,按字段规则拆分并转换数据类型:
parsed_data = [] for row in result["E_T_RFCDATA"]: raw_str = row["DATA"] parsed_row = {} current_pos = 0 for spec in field_specs: # 截取对应长度的字符串 field_value = raw_str[current_pos:current_pos + spec["length"]].strip() # 根据类型转换数据 if spec["type"] in ["N", "F"]: parsed_row[spec["name"]] = float(field_value) if spec["type"] == "F" else int(field_value) if field_value else None else: parsed_row[spec["name"]] = field_value current_pos += spec["length"] parsed_data.append(parsed_row) # 转换为DataFrame便于分析 df = pd.DataFrame(parsed_data) print(df)
3. 解决乱码问题
乱码源于编码不匹配,可通过以下两种方式处理:
- 连接时指定编码:
conn = pyrfc.Connection(ashost=ASHOST, sysnr=SYSNR, client=CLIENT, user=USER, passwd=PASSWD, lang=lang, codepage="UTF-8") - 解析时转换编码:
field_value = raw_str[current_pos:current_pos + spec["length"]].decode("ISO-8859-1").encode("UTF-8").strip()
4. 自定义RFC函数替代方案
若解析逻辑复杂,可在SAP系统创建自定义RFC函数,内部调用RSDRI_INFOPROV_READ_RFC和RSDRI_DATA_UNWRAP,直接返回结构化数据给Python,简化端侧解析。
内容的提问来源于stack exchange,提问作者dayidir
相关产品推荐
相关产品推荐

