Python xmlrpc库使用教程 Python实现XML-RPC远程调用

8次阅读

python xmlrpc.client需手动修复:强制设置content-type为text/xml、user-agent,禁用keep-alive,显式设timeout;datetime须转xmlrpc.client.datetime,bytes须用binary包装;遇faultcode需绕过serverproxy手动解析响应。

Python xmlrpc库使用教程 Python实现XML-RPC远程调用

Python 的 xmlrpc.client 库能用,但默认行为在现代服务端(尤其非 Python 实现的 XML-RPC 服务)上容易失败——不是库不行,是它对 http 头、编码、超时、错误响应的处理太“老派”。

XML-RPC 调用直接报 ProtocolError 或空响应

常见于调用 wordpress、Trac、旧版 jenkins 等服务时,ServerProxy 初始化或方法调用就崩,错误里带 HTTP Error 405Non-200 response 或直接卡住。根本原因是 xmlrpc.client.Transport 默认不发 Content-Type: text/xml,也不设 User-Agent,有些服务端会拒收。

  • 手动子类xmlrpc.client.Transport,重写 send_request()send_host(),强制加头:Content-Type 必须是 text/xml,不能是 application/xmlUser-Agent 建议设成 Python-xmlrpc/3.x
  • 禁用连接复用:在 make_connection() 返回的 http.client.HTTPConnection 上设 auto_open = False,避免 Keep-Alive 导致服务端混乱
  • 别依赖默认超时:显式传 timeout=10ServerProxy,否则可能卡死几十秒

datetimebytes 传参被静默转成字符串

XML-RPC 协议只定义了 dateTime.iso8601base64 两种类型,但 xmlrpc.clientdatetime 对象默认用 str() 转,结果发过去的是类似 '2024-05-20 14:30:00' 的普通字符串,服务端根本识别不了;bytes 同理,不包成 xmlrpc.client.Binary 就当普通字节流丢出去,解析失败。

  • 所有 datetime 必须包装成 xmlrpc.client.DateTime,注意它只接受 ISO 格式字符串或 time.struct_time,不接受原生 datetime 对象
  • bytes 数据必须用 xmlrpc.client.Binary(your_bytes) 包一层,否则服务端收到的是乱码或截断
  • 如果服务端要求严格区分 intFloat(比如某些 PHP XML-RPC 实现),传 42.0 前先 int(42.0),别指望自动转换

服务端返回 faultCode 却抛出 Fault 异常,没法拿到原始 XML

很多 XML-RPC 服务(如早期 Movable Type API)用 faultCode 表示业务错误(比如“文章不存在”),而不是真正异常。但 xmlrpc.client 遇到 <fault></fault> 就无条件抛 xmlrpc.client.Fault,你拿不到原始响应体,也没法看服务端返回的详细错误字段。

立即学习Python免费学习笔记(深入)”;

  • 绕过 ServerProxy,直接用 xmlrpc.client.Transportsingle_request() 方法,传入自己构造的 XML 请求体,捕获返回的 raw bytes,再手动解析 <fault></fault><params></params>
  • 或者用 urllib.request 手动 POST,把 XML body 当纯文本发,响应也当纯文本收,自己用 xml.etree.ElementTree 解析,虽然多几行,但完全可控
  • 别信文档里说的“自动重试”,ServerProxy 对网络抖动、502/503 一律不重试,得自己套 try/except + 指数退避

XML-RPC 不是 REST,它的类型系统和错误模型跟现代 HTTP 完全不同。最麻烦的不是调不通,而是调通了但参数语义错位、时间戳变成字符串、错误码被吞掉——这些都得在传输层动手,光靠 ServerProxy 包一层解决不了。

text=ZqhQzanResources