
简介面向需要在 Linux 环境下用 Python 调用 SAP RFC 接口的开发人员这是一份配套的 nwrfcsdk 资源包对应 nwrfc750P_5-70002752 版本解决 pyrfc 依赖的 C 库缺失、版本不匹配等安装与连接问题。压缩包共 27 个文件约 18.05MB以头文件、C/C 源码、动态库、配置文件等形式为主——其中 h/cpp/c 用于 SDK 编译与二次封装so 动态库和 ini 配置用于运行时加载与连接参数设定txt 文档则说明编译安装和环境变量配置要点。资源已由 1401 人学习下载。拿到后可按官方说明解压并配置 LD_LIBRARY_PATH 与 sapnwrfc.ini随后通过 pip 安装 pyrfc即可与 SAP NetWeaver 系统建立连接调用 STFC_CONNECTION 等远程函数读取表数据或触发业务逻辑。对从事 SAP 集成、自动化脚本开发或运维排障的工程师这份打包好的 SDK 能省去四处收集匹配版本的麻烦并支撑从环境搭建到代码联调的全过程。1. 为什么一个 Python 进程要抱着 SAP 的 C 基础库不放SAP 系统的 RFC 接口从来不是 Python 免费送的。想象这种场景你在一台连内网的 Linux 服务器上部署数据采集服务上游业务方只给了一个 SAP 账号和几个 RFC 函数名要求你半夜跑批读取物料主数据或过账凭证。面前有三条路买 JCo 中间件、让顾问导 CSV、或用 Python 直接调 RFC。真正试过第三条路的人都知道第一步不是pip install而是先弄到那份叫 NW RFC SDK 的 C 库。没有它pyRFC 连 import 都过不去。这篇文章就讲清楚在 Linux 上把 NW RFC SDK 装对、把 pyRFC 编译出来、把第一个 RFC 调用跑通顺手告诉你哪些错误换一台机器就能复现。适合已经拿到 RFC 授权、准备在 Linux 服务器上用 Python 对接 SAP 的开发或运维工程师。2. RFC 调用原理与方案选型为什么必须要有 nwrfcsdkRFC 不是一个普通的网络协议它是 SAP 私有的远程函数调用规范。消息头里携带 ABAP 数据字典的元信息所以 Python 这类外部语言不能凭一个 TCP 连接就把参数丢过去。真正干活的是 SAP 提供的 C 语言 SDK它负责把高层的调用请求翻译成 ABAP 工作进程能理解的报文。pyRFC 只是给这份 SDK 包了一层 Python 接口。2.1 RFC 协议里SDK 和 pyRFC 各自扮演什么角色RFC 链路由三部分构成SAP 应用服务器上的 ABAP 工作进程、网关进程gateway、以及外部程序一侧的 RFC 客户端库。SDK 就是那个客户端库。它实现了会话管理、数据序列化、类型转换和错误处理对外提供一组 C API核心的libsapnwrfc.so里包含RfcOpenConnection、RfcInvoke、RfcCloseConnection这些函数。pyRFC 用 Cython 将这些函数封装成 Python 类所以你看到的是一个pyrfc.Connection对象它内部其实持有一个指向 SDK 会话的指针。换句话说pyRFC 不是另一个 RFC 实现它只是绑定器。运行时的行为完全由 SDK 决定。为什么不自己写一个纯 Python 的 RFC 客户端因为 RFC 协议没有公开的协议文档SAP 也没有开放抓包接口贸然去实现会碰上大量黑匣子问题比如 Unicode 大端序、ABAP 结构体对齐等。用官方 SDK 是最快且唯一可靠的路。2.2 方案选型对比 JCo、sapnwrfc 和 REST 桥我这里直接给结论如果你的应用是 Python 写的并且部署在 Linux 上选 pyRFC 加 NW RFC SDK 是最契合的组合。对比 JCoJCo 需要企业版 Java 许可和大量 JVM 内存部署单元体积动辄几百 MB在容器化场景里显得笨重。对比第三方库sapnwrfc那个库只封装了老版 SDK 的部分函数没有持续兼容新版 SDK 的承诺遇到 SDK 更新后就容易失效。用 SAP Gateway 发 OData 用于轻量查询还行但高频、事务性强、返回值是深层嵌套结构体的场景RFC 的效率和稳定性还是高出一截。选型时还有一个识别要点真正能连 SAP 的 pyRFC 包名在 PyPI 上是pypyrfc导入名才是pyrfc。有些同名不同命的包会让人装上之后报ModuleNotFoundError所以安装时不要只看项目名要看安装包内是否依赖SAPNWRFC_HOME。这个识别方式能帮你避开大量假库。2.3 完整调用链从 Linux 进程到 ABAP 工作进程我们顺着一条调用请求走一遍看它在链路上经过哪些节点。首先pyRFC 初始化时调用RfcInitialize它创建 SDK 的运行时环境加载配置文件并初始化加密组件。然后pyrfc.Connection构造阶段调用RfcOpenConnection根据ashost、sysnr等参数向 SAP 网关发起 TCP 连接。网关进程监听在 33 加上系统号的端口比如系统号00对应 3300。连接建立后conn.call(STFC_CONNECTION, REQUTEXT...)会触发RfcInvokeSDK 把参数序列化成 RFC 消息报文经网关分发到某个 ABAP 工作进程执行。ABAP 端执行完把返回结构体序列化回传SDK 再还原成 Python 字典。这条链路每一步都有各自的失败模式TCP 不通报CPIC_ERRORABAP 执行异常报SYSTEM_FAILURESDK 与后端版本不匹配报INVALID_STATE。知道这些错在哪一层后面排查就能少走弯路。3. 在 Linux 上安装 NW RFC SDK目录布局、环境变量与依赖检查SDK 不是 pip 能直接装的东西它需要你到 SAP 支持门户手动下载。下载之前有两个决定成败的检查项平台架构和版本对齐。这两个问题如果一开始没想清楚后面会埋下很多隐性问题。3.1 下载前准备平台架构与版本选择打开 SAP 支持门户搜索 SAP NW RFC SDK进入下载页后选择 Linux 平台的x86_64版本。在服务器上执行uname -m确认系统是 64 位。如果是 ARM 机器SAP 虽然近几年也在试水但生产环境建议别碰因为 SDK 里的加密库和外部工具可能有小端序假设。版本选择上我的原则是“跟着后端 SAP 系统走”如果后端 ECC 系统比较老选一个新版 SDK 可能因为加密算法或协议细节不兼容而连不上反过来如果后端是新版 S/4HANA选太老的 SDK 又会缺加密套件。一般你可以在 SAP 官网看到 SDK 与 NetWeaver 版本的建议匹配关系没有明确说明的就选一个发布时间与后端系统维护期接近的稳定版。下载下来的文件通常是一个nwrfcsdk_*.tar.gz里面有完整目录和权限位。如果你的 SAP 账号权限有限也可以让 Basis 团队帮你下载后上传到内网源这在合规严格的客户现场很常见。3.2 解压 SDK 并理解目录结构解压之前先规划好安装根目录。我通常放在/opt/sap/nwrfcsdk用版本号子目录区分多版本再通过符号链接固定当前版本。这样以后升级时只需改链接不需要改任何环境变量和 pyRFC 指向。mkdir -p /opt/sap tar -xzf nwrfcsdk_*.tar.gz -C /opt/sap/ cd /opt/sap/nwrfcsdk find . -maxdepth 2 -type d | sort知识库解压后的典型目录包括lib、include、bin、doc。lib里面有libsapnwrfc.so、libsapucum.so、libsapcrypto.so、libicudata.so等include里有sapnwrfc.h。注意有些发行版解压后文件权限会丢尤其当压缩包是从 Windows 编辑过的共享库文件可能没有读权限。建议执行一次批量补权限chmod -R urX /opt/sap/nwrfcsdk find /opt/sap/nwrfcsdk -type f -name *.so -exec chmod 755 {} \;urX的意思是对文件加读权限对目录加执行权限避免把可执行文件权限改得太随意。find那行是给所有共享库补上执行位虽然 Linux 加载.so不要求执行位但部分部署工具会检查补上无害。3.3 设置环境变量并检查动态链接依赖SDK 装完后最关键的是让系统和 pyRFC 都能找到它。两个环境变量必须设置SAPNWRFC_HOME指向 SDK 根目录LD_LIBRARY_PATH指向 SDK 的lib目录。SAPNWRFC_HOME是 pyRFC 构建脚本读取 SDK 位置的唯一标准LD_LIBRARY_PATH是 Linux 动态加载器在运行时搜索共享库的开关。export SAPNWRFC_HOME/opt/sap/nwrfcsdk export LD_LIBRARY_PATH/opt/sap/nwrfcsdk/lib:$LD_LIBRARY_PATH echo export SAPNWRFC_HOME/opt/sap/nwrfcsdk /etc/profile.d/sapnwrfcsdk.sh echo export LD_LIBRARY_PATH/opt/sap/nwrfcsdk/lib:$LD_LIBRARY_PATH /etc/profile.d/sapnwrfcsdk.sh source /etc/profile.d/sapnwrfcsdk.sh提示如果用 systemd 部署 Python 服务记得在 service 文件里加EnvironmentSAPNWRFC_HOME/opt/sap/nwrfcsdk和EnvironmentLD_LIBRARY_PATH/opt/sap/nwrfcsdk/lib因为 systemd 不会自动读 profile 文件。这一个细节能省去线上服务重启后莫名其妙ImportError的麻烦。设置完成后用ldconfig刷新缓存然后检查 SDK 自身的依赖ldconfig /opt/sap/nwrfcsdk/lib ldd /opt/sap/nwrfcsdk/lib/libsapnwrfc.soldd输出里如果出现not found必须把缺失的系统库安装上。常见缺失项包括libgssapi_krb5.so.2、libuuid.so.1、libstdc.so.6。清掉这些not found再往后走否则 pyRFC 编译可能成功运行时却崩在libsapnwrfc.so的加载阶段而且报错非常隐晦。4. 编译安装 pyRFC构建选项、最小连接脚本与参数说明SDK 装好后开始处理 Python 侧。pyRFC 的安装不建议直接图省事装老版本 wheel因为在不同 Linux 发行版和 glibc 版本上预编译包经常因为 ABI 不匹配而报illegal instruction或直接崩溃源码编译反而更可控。4.1 准备编译工具链和虚拟环境先建虚拟环境避免把依赖撒得到处都是。很多线上服务器用的是 Python 3.6 或 3.8但 pyRFC 对新版 Python 的支持相对滞后建议优先用 3.10 或 3.11。python3.11 -m venv /opt/rfc_demo/venv source /opt/rfc_demo/venv/bin/activate pip install --upgrade pip setuptools wheel yum install -y gcc python3.11-devel cython39 # CentOS/RHEL 示例 apt install -y gcc python3.11-dev cython3 # Debian/Ubuntu 示例cython不是必须预装的因为 pyRFC 自带的 C 文件可以直接编译但预装可以避免某些特殊情况下的重编译失败。注意 Python 版本要和 dev 包对应否则编译时找不到Python.h。4.2 用 SAPNWRFC_HOME 编译安装 pyRFC如果在安装前没有设置SAPNWRFC_HOMEsetup.py 会直接报错退出如果设置了但路径写错会在编译后 import 阶段才暴露所以先手工确认环境变量。export SAPNWRFC_HOME/opt/sap/nwrfcsdk export CFLAGS-I$SAPNWRFC_HOME/include export LDFLAGS-L$SAPNWRFC_HOME/lib pip install pypyrfc编译过程中你会看到cythonize和gcc的日志。出现Successfully installed pypyrfc后先验证 importimport pyrfc print(pyrfc.__version__)如果报ImportError: libsapnwrfc.so: cannot open shared object file说明运行时路径不对再次确认/etc/profile.d的变量有没有被当前 shell 加载。如果报ModuleNotFoundError检查是否装成了别的同名包用pip uninstall pyrfc pypyrfc清干净重来。4.3 最小连接测试脚本STFC_CONNECTION 的完整代码一切就绪写第一个连接脚本。STFC_CONNECTION是 SAP 自带的 RFC 测试函数几乎不需要额外授权能跑通就说明链路是通的。import pyrfc config { ashost: 192.168.100.10, # SAP 应用服务器地址不要填消息服务器 sysnr: 00, # 系统号两位字符串 client: 100, # 客户端三位字符串 user: RFCUSER, passwd: your_password, lang: EN } conn pyrfc.Connection(**config) try: ret conn.call(STFC_CONNECTION, REQUTEXThello from linux python) print(ret[ECHOTEXT]) finally: conn.close()逻辑很简单构造连接参数创建连接调用STFC_CONNECTION回显输入字符串最后关闭连接。注意sysnr和client必须写成字符串形式sysnr为00时不能写成0否则 SDK 拼接端口和客户端时会少一位直接导致CPIC_ERROR。lang不写默认用系统默认语言如果系统默认是中文回显时要用repr()看内容避免控制台乱码。4.4 运行测试并理解返回结果与常见异常运行时如果打印出了ECHOTEXT恭喜你链路是通的。如果报错先看异常类型再分析RFC_CPIC_ERROR是网络或端口问题RFC_INVALID_STATE是 SDK 版本和 SAP 系统不匹配RFC_SYS_EXCEPTION是 ABAP 侧抛了异常比如权限或参数值不合法。还有一类少见的MemoryError常发生在数据缓冲区不匹配时这时检查 SDK 与 pyRFC 的位数一致性即可。返回结果永远是一个字典或嵌套字典SAP 的表类型结构体会被解析成 list of dict。这个约定从 pyRFC 早期版本到现在一直稳定所以后面写业务代码时完全可以用 JSON 序列化结果做落库。5. 避坑Linux 下 pyRFC 连 SAP 的 5 个翻车现场这一章写的是血泪经验。以下错误几乎每个项目里都会遇到报错信息又短又抽象不还原现场很难看明白。我按阶段整理每条按现象、原因、解决步骤列出。5.1 导入阶段ImportError 与初始化失败现象一import pyrfc直接报ImportError: libsapnwrfc.so: cannot open shared object file没有任何其他上下文。原因运行时动态加载器找不到 SDK 库通常是LD_LIBRARY_PATH没有被正确导出或者 systemd 服务没有继承 profile 里的变量。解决在命令行执行echo $LD_LIBRARY_PATH没有输出就 source 一次如果是 systemd 服务必须在 service 文件里用Environment显式声明。现象二导入成功但pyrfc.Connection构造时报RuntimeError: Initialization of the RFC library failed。原因SDK 初始化时依赖的时间同步、加密库或本地配置出问题。解决检查系统时间与 SAP 应用服务器偏差安装libsapcrypto.so的依赖用ldd查看必要时清理/opt/sap/nwrfcsdk下残留的旧版本库文件。5.2 连接阶段sysnr 格式和网关端口现象pyrfc.Connection抛RFC_CPIC_ERROR错误码里包含LOCATION: CPIC (TCP/IP)。原因第一嫌疑是sysnr填了0而不是00导致 SAP 网关端口拼接错误第二嫌疑是防火墙只放行了业务网络端口没放行33xx网关端口。解决先把sysnr改成两位字符串然后用nc -zv ashost 3300测试端口通不通不通就找网络管理员。另外如果应用服务器前面有负载均衡设备把ashost配成 VIP 地址很可能连接超时因为 RFC 协议不遵循 HTTP 那种静态负载均衡的转发方式。解决是直接配置实际的应用服务器主机名或 IP让 SDK 自己完成会话管理。5.3 调用阶段权限、接口和 Unicode现象连接成功但conn.call(BAPI_MATERIAL_GETLIST)报RFC_AUTHORIZATION_FAILURE。原因RFC 账号缺少该 BAPI 的授权对象最常见的是S_RFC授权缺失。解决在 SAP 的 SU01 事务里给账号加授权授权的内容可以明确到功能组或函数名。授权不是看一遍代码就能绕过的必须由 SAP 管理员操作。现象调用成功但返回的中文变成乱码或字符串长度不对。原因连接参数没有显式设置lang且 SDK 和 SAP 之间的字符集协商用了非 Unicode。解决连接参数里加lang: ZH或EN确认 SAP 系统是 Unicode 模式在 pyRFC 较新版本里还可以传参数RFC_INTERNAL控制内部编码转换。5.4 编译阶段Cython 版本和 Python 版本现象pip install pypyrfc报cythonize相关错误堆栈里出现AttributeError: module。原因Cython 版本过新或过旧与 pyRFC 的源码构建不兼容。解决固定 Cython 版本再重新编译比如指定一个与当前 Python 兼容的版本然后再次执行pip install pypyrfc --no-binary :all:。如果系统自带 Python 3.12建议换到 3.10 或 3.11很多扩展到 3.12 才出现的编译问题可以立刻消失。5.5 架构一致性Python 位数和 SDK 位数现象import pyrfc成功但pyrfc.Connection初始化时进程直接崩溃SIGSEGV 或Fatal Python error不留下 Python traceback。原因SDK 是 64 位但 Python 解释器是 32 位SDK 的指针运算在 32 位进程中越界。解决用file命令确认 SDK 中的.so是 64 位用python -c import platform; print(platform.architecture())确认解释器是 64 位两边对齐后问题消失。6. 进阶多 SAP 系统配置管理、线程安全与调用前健康检查最后分享一个我养成的习惯永远把连接配置从代码里拆出去。尤其在生产环境要对接开发、测试、生产三套 SAP 系统时代码里写死ashost和账号是过一天就翻车的写法。常见做法是维护一个systems.json按环境名存连接参数密码从环境变量里取不落盘。import json, os, socket, pyrfc def load_system(name): with open(/opt/rfc_demo/systems.json) as f: systems json.load(f) cfg systems[name].copy() cfg[passwd] os.environ.get(SAP_PASSWORD, cfg.get(passwd)) return cfg def rfc_port(sysnr): return 3300 int(sysnr) def system_ok(cfg, timeout3): with socket.create_connection((cfg[ashost], rfc_port(cfg[sysnr])), timeouttimeout): return True return False cfg load_system(DEV) if system_ok(cfg): conn pyrfc.Connection(**cfg) try: ret conn.call(STFC_CONNECTION, REQUTEXThealthcheck) print(ret[ECHOTEXT]) finally: conn.close()这套脚本的价值是部署完先跑一次能立即定位 SDK 路径、网络、权限三层问题日常批处理启动前也建议先调用健康检查避免把整个任务拖进超时重试。还有一个线程安全的点pyRFC 的连接对象不能跨线程共用每个线程必须独立创建Connection。如果要并发批量调用可以在线程池里对每个线程初始化连接而不是共享一个连接对象。我在一个临时方案里因为贪图方便共享了连接结果数据量大了之后偶发报错最后定位到是 RFC 会话的线程安全问题。现在我的习惯是每个线程持有自己的连接用完立刻关闭宁可多几次建连也不拿数据完整性冒险。希望帮到你——和 SAP 打交道把环境变量和连接生命周期管好这一层稳定了后面的业务代码才值得信赖。本文还有配套的精品资源点击获取