之前我有比较系统地讲解过 SAP 接口编程,但没有使用 Python 语言的,主要是因为没有一个合适的 package。偶见几篇介绍 PyRFC 的文章,看到 pyrfc 对 unicode 的支持实在不敢恭维,没有任何尝试的欲望。现在 PyRFC 已经演进到了 2.1 版(https://pypi.org/project/pynwrfc/),感觉 1.9 版后出现了质的飞跃,代码在 Github 上开源(https://github.com/SAP/PyRFC)。由于 Python 语言的简洁,是开发 SAP 接口编程一个不错的选择了。
Windows 安装 PyRFC 的方法
安装 SAP NW RFC SDK
PyRFC 的主要难点在安装,我以 Windows 10 系统为例介绍安装的方法。PyRFC 是用 Python 语言对 SAP NW RFC SDK 的一个封装,使得 Python 可以方便地调用 SAP 的 BAPI。SAP NW RFC SDK 是 C 语言编写的用于访问 SAP BAPI 的开发工具包 (Development kit),在安装 PyRFC 之前,要先安装 SAP NW RFC SDK,这个开发工具包是向后兼容的,安装的时候,可以选择最新的版本。SAP 官方(https://support.sap.com/ ) 提供下载,但需要有下载权限。
这是一个压缩包,解压之后,里面的文件夹结构是这样的:
把 META-INF 文件夹和 SIGNATURE.SMF 文件移入 nwrfcsdk 文件夹,这样 nwrfcsdk 文件夹的结构应该是这样的:
然后配置环境变量。首先配置 SAPNWRFC_HOME 环境变量:
接下来配置 Path 环境变量,将 nwrfcsdk 文件夹下面的 lib 和 bin 文件夹加入到 Path 环境变量:
这里有一个细节,我前面刻意改变了 META-INF 文件夹和 SIGNATURE.SMF 文件 的位置,是因为我安装 PyRFC 后,出现 DLL 加载错误:
ImportError: DLL load failed: 找不到指定的模块。
刚开始以为是环境变量配置错误的原因,经检查环境变量配置没有问题但还是出错,经查看 pyrfc 的源码,看到代码文件 _init_.py 有一段关于加载 dll 的代码:
这说明, lib 文件夹应该是 SAPNWRFC_HOME 环境变量指向文件夹直接下层文件夹。
安装 PyRFC
PyRFC 支持 pip 方式安装,但这里大家可能碰到两个比较棘手的问题。首先 pip install pyrfc 只支持 0.12 版本的安装,这个版本太老,不适合使用。第二是 pip install pynwrfc 安装 pyrfc 现在最新版是 2.1,可能与 SAP NW RFC SDK 版本冲突,出现找不到 DLL 错误。这个时候,大家要尝试 pyrfc 选择一个合适的pyrfc 版本。我测试的时候,nwrfc750P_0-70002755 和 pyrfc1 .9.9 版本没有问题。大家在这里可以找到 pyrfc 的各个版本:https://github.com/SAP/PyRFC/tags
根据操作系统和 Python 的版本,选择合适的包下载,用 pip install pyrfc-1.9.99-cp37-cp37m-win_amd64.whl 进行本地 wheel 文件的安装。
安装完成后,进入 Python 环境,查看 pyrfc 和 NW RFC SDK 的版本:
import pyrfc
print (pyrfc.__version__) # 检查 pyrfc 的版本
print (pyrfc.get_nwrfclib_version()) # 检查 SAP NW RFC SDK 的版本
PyRFC 使用示例
PyRFC 的使用比较简单:
- 设置登录参数,通过 Connection() 方法获取 SAP 的连接,PyRFC 自动管理连接,不需要手工打开和关闭,登录参数可以是字典类型的参数,见下面示例
- 通过 connection.call() 方法调用 SAP BAPI,不区分 Import, Export 和 Table 等参数类型,用关键字参数对应 SAP 的参数
- Table 参数通过列表(list) 和字典(dict) 的组合来表达,参见下面的 OPTIONS 参数
以 RFC_READ_TABLE 函数为例,下面的代码展示了如何使用 PyRFC 获取 SAP 示例数据 SPFLI 表的内容。输出显示用到了 Python 第三方 tablib 库。
import pyrfc
import tablib
conn_params = {
"user": "stone",
"passwd": "123456",
"ashost": "192.168.44.100",
"sysnr": "00",
"lang": "EN",
"client": "001"
}
def read_table():
conn = pyrfc.Connection(**conn_params)
option_parameter = [
{"TEXT": "COUNTRYFR EQ 'US' "}
]
result = conn.call('RFC_READ_TABLE',
QUERY_TABLE = "SPFLI",
DELIMITER = ",",
OPTIONS = option_parameter)
# 获取 FIELDS 表参数
fields = tablib.Dataset()
fields.dict = result['FIELDS']
print(fields)
# 获取 DATA 表参数
data = tablib.Dataset()
data.dict = result['DATA']
print(data)
if __name__ == "__main__":
read_table()
运行程序的结果如下: