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

Python 的 xmlrpc.client 库能用,但默认行为在现代服务端(尤其非 Python 实现的 XML-RPC 服务)上容易失败——不是库不行,是它对 HTTP 头、编码、超时、错误响应的处理太“老派”。
XML-RPC 调用直接报 ProtocolError 或空响应
常见于调用 WordPress、Trac、旧版 Jenkins 等服务时,ServerProxy 初始化或方法调用就崩,错误里带 HTTP Error 405、Non-200 response 或直接卡住。根本原因是 xmlrpc.client.Transport 默认不发 Content-Type: text/xml,也不设 User-Agent,有些服务端会拒收。
- 手动子类化
xmlrpc.client.Transport,重写send_request()和send_host(),强制加头:Content-Type必须是text/xml,不能是application/xml;User-Agent建议设成Python-xmlrpc/3.x - 禁用连接复用:在
make_connection()返回的http.client.HTTPConnection上设auto_open = False,避免 Keep-Alive 导致服务端混乱 - 别依赖默认超时:显式传
timeout=10给ServerProxy,否则可能卡死几十秒
datetime 和 bytes 传参被静默转成字符串
XML-RPC 协议只定义了 dateTime.iso8601 和 base64 两种类型,但 xmlrpc.client 对 datetime 对象默认用 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)包一层,否则服务端收到的是乱码或截断 - 如果服务端要求严格区分
int和float(比如某些 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.Transport的single_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 包一层解决不了。








