简介:Linux环境下,用Python连接SAP系统,常需借助pyrfc与nwrfcsdk。该组件包正面向此类集成开发场景,为需要安装配置SAP NW RFC SDK、并通过Python调用RFC功能的工程师提供了一整套可用文件。压缩包共含27个文件,以头文件(.h)、C/C++源码(.c/.cpp)、动态库(.so)、配置文件(.ini)和可执行工具为主,整体大小约18.05MB,能较好支撑pyrfc绑定的编译与运行时环境搭建;资源发布后已有1384人学习使用,适合正在搭建SAP RFC连接环境、需要排查nwrfcsdk配置问题的开发者参考。包内包含nwrfc750P_5-70002752的关键SDK组件,如include头文件、bin目录下的RFC可执行工具,以及用于签名校验和版本管理的元数据文件,便于核对版本和完整性;另附示例与文档目录,便于快速对照接口调用方法,结合SDK安装、环境变量设置到RFC函数调用等关键环节,可帮助读者在企业级SAP集成与自动化运维场景中快速上手。 最近在Linux服务器上做SAP外围系统集成,需要让Python应用直接调SAP里的RFC函数。跑通这条路的关键是pyrfc这个Python库,而pyrfc底层又强依赖SAP官方发布的NW RFC SDK(nwrfcsdk)。中间踩了一串坑,正好把从下载SDK到成功调用RFC的完整过程写下来,给要做同类对接的同学参考。
如果你手头有SAP系统,又需要在Linux环境下用Python写脚本或者服务,去查询物料、创建订单、同步主数据等,这套方案是目前最直接的路子。它不像中间件方案那样需要额外部署一堆组件,pyrfc本身就是SAP对外提供的Python绑定,连接方式接近ABAP侧的RFC调用习惯,学习成本相对低。下面从环境准备开始讲,全程按我实际操作的顺序来。
1. 整体思路与选型考量
1.1 这套方案的本质是什么
先理一下调用链。Python侧发起RFC调用,走的是pyrfc封装好的接口,pyrfc本身是Cython编写的扩展库,它通过SAP官方提供的NW RFC SDK(C/C++动态库)和SAP应用服务器建立连接,最终在ABAP侧执行对应的函数模块(FM)。
所以本质上,pyrfc只是“翻译层”,真正干活的是nwrfcsdk。这就是为什么你光用pip装一个pyrfc还不够,还必须先装好对应版本的SDK,并且让系统能找到它的动态库,否则导入pyrfc就会报错。
和SAP其他集成方式相比,pyrfc更适合这种场景:需要快速写一个Python服务,直接调SAP里的BAPI或RFC函数,且不想引入SAP PI/PO、云平台集成套件这类重量级中间件。它和RFC函数之间的映射很直接,不需要额外定义接口模型,参数以Python的数据结构传入,返回结果也是字典和列表,处理起来非常顺手。
1.2 为什么不用别的方案
很多人在选型时会纠结:要不要用SAP Java Connector(JCo)、SAP .NET Connector(NCo),或者干脆走REST/OData?我个人的判断标准是:如果技术栈已经是Python占主导,且外围系统只需要“调用几个RFC函数完成业务闭环”,pyrfc就是成本最低的选择。
- JCo面向Java生态,如果你没有Java服务,引入它等于额外维护一套JVM应用。
- OData虽然有标准接口,但很多老的RFC函数并不是已经暴露成OData服务的,要额外开发网关服务。
- pyrfc的优势在于进程内调用,部署简单,脚本也可以直接跑,运维负担小。
当然,如果你们需要处理大量异步消息、做复杂映射,那可能需要更完整的企业集成平台,这是另一套思路了。
2. Linux环境准备与SDK安装
2.1 环境清单
我这里实测的部署环境是CentOS 7.9,Python版本3.8。SDK用的是SAP NW RFC SDK 7.55,这个版本目前兼容性比较好,和PyRFC较新版本配合没有遇到版本不匹配的问题。
- 操作系统:CentOS 7.9(x86_64)
- Python:3.8(建议3.7以上,不要用2.7了)
- SAP NW RFC SDK:7.55
- PyRFC:2.5.x
- 底层依赖:gcc、make、python3-devel(如果安装PyRFC时需要本地编译)
注意:SAP官方发布的nwrfcsdk只提供64位版本,所以你的Linux系统必须是x86_64架构。如果系统是ARM架构,官方SDK默认不支持,基本只能换方案。
2.2 下载并安装nwrfcsdk
nwrfcsdk要从SAP官方软件渠道下载,一般需要SAP S-user账号。下载页面里找“SAP NW RFC SDK”对应的Linux版本,解压之后就是标准的目录结构,包含lib、include等目录。
我习惯把SDK放到/opt/nwrfcsdk,这个路径一目了然。解压命令不复杂:
mkdir -p /opt/nwrfcsdk tar -xzf nwrfcsdk_xxx.tar.gz -C /opt/nwrfcsdk解压后检查一下lib目录,核心文件是libsapnwrfc.so,还会带一些ICU相关的动态库。这一步能不能找到正确的文件,直接决定后面会不会报“找不到共享库”的错。
2.3 配置SAPNWRFC_HOME与动态库路径
安装完SDK之后,最关键的是设置环境变量。PyRFC在导入时会去读SAPNWRFC_HOME这个环境变量,所以要把它加到系统配置里,同时还需要把SDK的lib目录加入动态库搜索路径。
export SAPNWRFC_HOME=/opt/nwrfcsdk export LD_LIBRARY_PATH=$SAPNWRFC_HOME/lib:$LD_LIBRARY_PATH如果是临时测试,直接在当前shell执行这两行。如果是长期使用,建议写到/etc/profile.d/sapnwrfc.sh里:
cat > /etc/profile.d/sapnwrfc.sh <<'EOF' export SAPNWRFC_HOME=/opt/nwrfcsdk export LD_LIBRARY_PATH=$SAPNWRFC_HOME/lib:$LD_LIBRARY_PATH EOF chmod +x /etc/profile.d/sapnwrfc.sh这里有个细节:如果系统里同时有多个版本的SDK,很容易出现版本错乱。我的建议是只保留实际要用的那个SDK,并把SAPNWRFC_HOME写死,不要让它去猜。另外不要用软链接把SDK放到/usr/lib里,除非你能确认所有动态库依赖都干净,否则后续排查问题会比较累。
3. Python端安装pyrfc并打通连接
3.1 创建虚拟环境安装pyrfc
强烈建议用虚拟环境,不要让Python包污染系统环境。我这边用venv:
python3 -m venv venv source venv/bin/activate pip install --upgrade pip pip install pyrfc如果一切正常,pip会直接装上pyrfc。此时先做一次导入测试:
python -c "from pyrfc import Connection; print('ok')"如果输出ok,说明SDK路径和动态库都已经识别。如果这步就报错,先不要急着调连接,回到环境变量和SDK依赖那一步排查。
3.2 连接参数与最小验证脚本
SAP连接参数主要分两种:应用服务器直连和消息服务器负载均衡。前者最常用,参数包括ashost(应用服务器地址)、sysnr(系统编号)、client(客户端)、user(用户名)、passwd(密码)。
下面是最小可运行脚本:
from pyrfc import Connection conn = Connection( ashost='192.168.10.10', sysnr='00', client='100', user='RFCUSER', passwd='PASSWORD' ) print(conn.get_system_info()) conn.close()能打印出系统信息,说明网络、账号权限、SDK、PyRFC整条链路都已经通了。这个脚本可以作为任何后续代码的“探针”,先跑通它,再往上层写业务逻辑。
3.3 调用RFC函数的基础写法
连接通了之后,调用函数就很简单,核心是conn.call方法:
from pyrfc import Connection conn = Connection( ashost='192.168.10.10', sysnr='00', client='100', user='RFCUSER', passwd='PASSWORD' ) try: result = conn.call('BAPI_COMPANY_GETLIST') for company in result.get('COMPANY_LIST', []): print(company) finally: conn.close()这里的BAPI_COMPANY_GETLIST是一个BAPI,返回的COMPANY_LIST是一张表。pyrfc会自动把SAP的表转成Python的list,每行是一个dict,字段名和SAP结构里的字段名保持一致,处理起来和操作普通JSON没有区别。
带参数的调用也类似,比如调用BAPI_MATERIAL_GETLIST时传MAXROWS:
result = conn.call('BAPI_MATERIAL_GETLIST', MAXROWS=50)如果是结构参数,直接传dict;如果是行项目表,传list of dict。这和SAP RFC的层级结构天然对应。
4. 业务场景中的常见操作与注意事项
4.1 参数、表结构与返回数据解析
实际做业务集成时,最花时间的往往不是连接,而是参数映射。SAP RFC函数的输入输出参数有单值、结构、内表三层形态,pyrfc里的映射规则是:
- 单值(SCALAR):直接传Python字符串、整数等。
- 结构(STRUCTURE):用一个Python dict表示。
- 内表(TABLE):用一个list of dict表示,即使只有一行也要用list包起来。
举一个实际的例子,调用BAPI_GOODSMVT_CREATE做物料过账时,需要传入抬头结构和行项目表:
header = { 'PSTNG_DATE': '2025.01.10', 'DOC_DATE': '2025.01.10', 'HEADER_TXT': 'Python created' } items = [ { 'MATERIAL': 'MAT001', 'PLANT': '1000', 'STGE_LOC': '0001', 'MOVE_TYPE': '261', 'ENTRY_QNT': '10', } ] result = conn.call( 'BAPI_GOODSMVT_CREATE', GOODSMVT_HEADER=header, GOODSMVT_ITEM=items, )很多BAPI需要先调用,再根据返回值决定是否调用BAPI_COMMIT,这点和SAP GUI里的操作逻辑一致。千万不要漏掉事务提交,不然业务数据不会真正生效。
4.2 连接配置管理:别把密码写死在代码里
不少同学的第一个测试脚本会把密码直接写在Python文件里,这在你本机验证没毛病,但一旦脚本要部署到服务器或者进Git仓库,就是事故隐患。
我的做法是用环境变量配合python-dotenv管理连接信息:
pip install python-dotenv项目目录下建.env文件:
SAP_ASHOST=192.168.10.10 SAP_SYSNR=00 SAP_CLIENT=100 SAP_USER=RFCUSER SAP_PASSWD=CHANGE_MEPython里这样读取:
import os from dotenv import load_dotenv from pyrfc import Connection load_dotenv() conn = Connection( ashost=os.getenv('SAP_ASHOST'), sysnr=os.getenv('SAP_SYSNR'), client=os.getenv('SAP_CLIENT'), user=os.getenv('SAP_USER'), passwd=os.getenv('SAP_PASSWD'), )同时把.env加入.gitignore,避免误提交。如果公司有密钥管理平台,优先从密钥服务里拉取密码,这里只是一个通用做法。
4.3 SAP侧权限与授权检查
Python这边把参数都写对了,但调用还是报权限错误,这是最常见的坑之一。SAP的RFC调用其实也遵循ABAP权限体系,用户的授权角色里必须包含S_RFC授权对象,并且分配对应的函数组权限。
简单说,SAP端要创建一个专门给外围系统用的RFC用户,不要拿业务人员账号来连。给这个用户分配的角色里加上RFC访问权限,并限定允许调用的函数组范围。如果SAP Basis团队有自己的一套流程,直接按他们的要求去申请就好。
如果在调用时遇到RFC_AUTHORIZATION_FAILURE这类错误,优先查SAP端用户的权限,代码这边能做的事情不多。
5. 常见问题速查与踩坑记录
5.1 高频报错对照表
这里整理了我实际遇到以及帮别人排查过的几类典型问题,按报错关键词分类:
| 报错现象 | 可能原因 | 解决办法 |
|---|---|---|
| import pyrfc后提示找不到SDK | SAPNWRFC_HOME未设置或设置错误 | 检查环境变量是否生效,确认SDK路径正确 |
| 报错libsapnwrfc.so找不到 | LD_LIBRARY_PATH未包含SDK的lib目录 | 在环境变量中追加$SAPNWRFC_HOME/lib |
| 报错版本不支持 | SDK版本和PyRFC版本不匹配 | 换用SAP NW RFC SDK 7.55,保持PyRFC升级到2.x较新版本 |
| RFC_COMMUNICATION_FAILURE | 网络不通、SAP系统未启动或防火墙拦截 | 先测试SAP服务器端口(默认33xx),确认网络可达 |
| RFC_LOGON_FAILURE | 账号密码错、客户端编号错、账号锁定 | 检查凭据,联系SAP Basis确认账号状态 |
| RFC_AUTHORIZATION_FAILURE | 用户没有对应RFC权限 | 在SAP端添加S_RFC授权 |
| 中文乱码 | 系统locale和SAP字符编码不一致 | 检查服务器locale,确保支持UTF-8 |
5.2 几个容易忽略的坑
第一个坑:CentOS系统缺少某些基础库。SDK里的动态库依赖glibc和ICU等系统库,如果系统环境太精简,比如最小化安装的服务器,可能会出现Symbol not found之类的错误。解决方法是装好基础工具链:
yum install -y gcc make glibc-devel libicu-develUbuntu/Debian系则是:
apt-get install -y build-essential python3-dev libicu-dev第二个坑:多个Python环境混用。因为pyrfc需要读取环境变量,如果你用system python和venv来回切换,很容易出现“明明pip装好了,运行却找不到模块”的情况。建议每个项目独立虚拟环境,在启动脚本里显式source环境变量文件,不要依赖全局配置。
第三个坑:连接对象复用。部分场景下如果每次都新建连接,SAP侧的会话会不断增长,长时间运行后可能导致系统资源不足。轻量级脚本无所谓,但如果是常驻服务,建议用一个简单的连接池或至少复用同一个Connection对象,在服务退出时统一close。
5.3 一些实用排查习惯
连接不上SAP时,不要急着盯Python代码,先在Linux命令行测试端口通不通:
telnet 192.168.10.10 3300SAP实例的网关端口通常是33xx,xx对应系统编号。如果端口不通,后面调RFC一定失败,这不是PyRFC本身能解决的。
PyRFC本身调试信息也很有用,可以在日志里开启详细输出。我用的是标准logging模块,把pyrfc相关logger级别调到DEBUG,能看到更多底层连接细节:
import logging logging.basicConfig(level=logging.DEBUG)这样跑一次调用,能直观看到请求发出去和响应返回的情况,比盲猜快很多。
最后再分享一个小技巧:给pyrfc调用包一层简单的工具函数,统一处理连接、异常、关闭,避免每个业务脚本都重复写一段连接代码。踩过几次坑之后,你会发现这层封装能省掉后续大量精力。
本文还有配套的精品资源,点击获取