xmlrpclib

注意

xmlrpclib模块已被重命名为xmlrpc.clientPython 3. 当将源代码转换为Python 3时,2to3工具将自动适应导入。

2.2版本中的新功能。

源代码: Lib / xmlrpclib.py

XML-RPC是一种远程过程调用方法,它使用通过HTTP(S)传递的XML作为传输。通过它,客户端可以使用远程服务器上的参数调用方法(服务器通过URI命名)并获取结构化数据。该模块支持编写XML-RPC客户端代码; 它处理所有在线上一致的Python对象和XML之间的转换细节。

警告

xmlrpclib模块对恶意构建的数据不安全。如果您需要解析不可信或未经身份验证的数据,请参阅XML漏洞。

在版本2.7.9中更改:对于HTTPS URI,xmlrpclib现在默认执行所有必需的证书和主机名检查。

class xmlrpclib.ServerProxy(uri[, transport[, encoding[, verbose[, allow_none[, use_datetime[, context]]]]]])

ServerProxy实例是管理与远程XML-RPC服务器的通信的对象。所需的第一个参数是一个URI(统一资源指示符),通常是服务器的URL。可选的第二个参数是一个传输工厂实例; 默认情况下它是SafeTransporthttps:URL的内部Transport实例,否则是内部HTTP 实例。可选的第三个参数是一个编码,默认为UTF-8。可选的第四个参数是一个调试标志。

以下参数控制使用返回的代理实例。如果allow_none为true,则Python常量None将被转换为XML; 默认行为是为了None引发一个TypeError。这是XML-RPC规范的常用扩展,但并不受所有客户端和服务器的支持; 有关说明,请参阅http://ontosys.com/xml-rpc/extensions.php。所述use_datetime标志可用于引起日期/时间值被表示为datetime.datetime对象; 这在默认情况下是错误的。datetime.datetime对象可能会传递给调用。

HTTP和HTTPS传输都支持HTTP基本认证的URL语法扩展:http://user:pass@host:port/path。该user:pass部分将被base64编码为HTTP'授权'标头,并在调用XML-RPC方法时作为连接过程的一部分发送到远程服务器。如果远程服务器需要基本身份验证用户和密码,则只需使用它。如果提供了HTTPS URL,上下文可以ssl.SSLContext并配置基础HTTPS连接的SSL设置。

返回的实例是一个代理对象,其中的方法可用于在远程服务器上调用相应的RPC调用。如果远程服务器支持introspection API,则该代理还可用于向远程服务器查询其支持的方法(服务发现)并获取其他服务器关联的元数据。

可以整合的类型(例如,可以通过XML进行编组)的类型包括以下内容(除非另有说明,否则它们被解组为相同的Python类型):

XML-RPC类型

Python类型

布尔

布尔

int或i4

int或长范围从-2147483648到2147483647。

浮动

str或unicode

排列

包含可整合元素的列表或元组。数组返回为列表。

结构

字典。键必须是字符串,值可以是任何适合的类型。用户定义的类的对象可以传入; 只传输__dict__属性。

dateTime.iso8601

DateTime或datetime.datetime。返回的类型取决于use_datetime标志的值。

BASE64

二进制

无常数。仅当allow_none为真时才允许传递。

这是XML-RPC支持的全套数据类型。方法调用还可能引发一个特殊的Fault实例,用于发送XML-RPC服务器错误,或ProtocolError用于在HTTP / HTTPS传输层中发出错误信号。双方FaultProtocolError从被称为基类派生Error。请注意,即使从Python 2.2开始,您可以创建内置类型的子类,但xmlrpclib模块当前不会编组这些子类的实例。

传递字符串时,XML等特殊字符(例如<>&将被自动转义。但是,调用者有责任确保该字符串不含XML中不允许使用的字符,例如ASCII值介于0和31之间的控制字符(当然除了tab,newline和回车); 如果不这样做将导致XML-RPC请求不是格式良好的XML。如果您必须通过XML-RPC传递任意字符串,请使用Binary下面描述的包装类。

Server被保留作为ServerProxy向后兼容的别名。新的代码应该使用ServerProxy

在版本2.5中更改:添加了use_datetime标志。

在版本2.6中进行了更改:如果具有___dict___属性并且没有以特殊方式编组的基类,则可以传入新样式类的实例。

在版本2.7.9中更改:添加了上下文参数。

1. ServerProxy对象

ServerProxy实例具有对应于由XML-RPC服务器接受每个远程过程调用的方法。调用该方法将执行由名称和参数签名调度的RPC(例如,可以使用多个参数签名重载相同的方法名称)。该RPC完成通过返回一个值,在符合的类型或它们可以是返回的数据FaultProtocolError对象指示错误。

支持XML内省API的服务器支持在保留system属性下分组的一些常用方法:

ServerProxy.system.listMethods()

此方法返回一个字符串列表,XML-RPC服务器支持的每个(非系统)方法都有一个字符串列表。

ServerProxy.system.methodSignature(name)

此方法接受一个参数,即由XML-RPC服务器实现的方法的名称。它为此方法返回一组可能的签名。签名是一个类型数组。这些类型中的第一个是方法的返回类型,其余的是参数。

由于允许多个签名(即重载),因此此方法返回签名列表而不是单例。

签名本身仅限于方法所期望的顶级参数。例如,如果一个方法需要一个结构数组作为参数,并且它返回一个字符串,那么它的签名就是“string,array”。如果期望三个整数并返回一个字符串,则其签名是“string,int,int,int”。

如果没有为该方法定义签名,则返回一个非数组值。在Python中,这意味着返回值的类型将不是列表。

ServerProxy.system.methodHelp(name)

此方法接受一个参数,即由XML-RPC服务器实现的方法的名称。它返回一个描述该方法用法的文档字符串。如果没有这样的字符串可用,则返回空字符串。文档字符串可能包含HTML标记。

2.布尔对象

这个类可以从任何Python值初始化; 返回的实例仅取决于其真值。它支持通过各种Python的运营商__cmp__()__repr__()__int__(),和__nonzero__()方法,都在明显的方式来实现。

它还有以下方法,主要用于解组代码的内部使用:

Boolean.encode(out)

将此布尔项的XML-RPC编码写入输出流对象。

下面是一个工作示例。服务器代码:

import xmlrpclib
from SimpleXMLRPCServer import SimpleXMLRPCServer

def is_even(n):
    return n % 2 == 0

server = SimpleXMLRPCServer(("localhost", 8000))
print "Listening on port 8000..."
server.register_function(is_even, "is_even")
server.serve_forever()

上述服务器的客户端代码:

import xmlrpclib

proxy = xmlrpclib.ServerProxy("http://localhost:8000/")
print "3 is even: %s" % str(proxy.is_even(3))
print "100 is even: %s" % str(proxy.is_even(100))

3.日期时间对象

class xmlrpclib.DateTime

这个类可以在历元以来的秒数,时间元组,ISO 8601时间/日期字符串或datetime.datetime实例中初始化。它具有以下方法,主要用于编组/解编码的内部使用:

decode(string)

接受一个字符串作为实例的新时间值。

encode(out)

将此DateTime项目的XML-RPC编码写入输出流对象。

它还支持某些Python的内置操作符__cmp__()__repr__()方法。

下面是一个工作示例。服务器代码:

import datetime
from SimpleXMLRPCServer import SimpleXMLRPCServer
import xmlrpclib

def today():
    today = datetime.datetime.today()
    return xmlrpclib.DateTime(today)

server = SimpleXMLRPCServer(("localhost", 8000))
print "Listening on port 8000..."
server.register_function(today, "today")
server.serve_forever()

上述服务器的客户端代码:

import xmlrpclib
import datetime

proxy = xmlrpclib.ServerProxy("http://localhost:8000/")

today = proxy.today()
# convert the ISO8601 string to a datetime object
converted = datetime.datetime.strptime(today.value, "%Y%m%dT%H:%M:%S")
print "Today: %s" % converted.strftime("%d.%m.%Y, %H:%M")

4.二进制对象

class xmlrpclib.Binary

这个类可以从字符串数据(可能包括NULs)初始化。Binary对象内容的主要访问由一个属性提供:

data

Binary实例封装的二进制数据。数据以8位字符串的形式提供。

Binary 对象具有以下方法,主要用于编组/解编码的内部使用:

decode(string)

接受base64字符串并将其解码为实例的新数据。

encode(out)

将此二进制项的XML-RPC base 64编码写入输出流对象。

按照RFC 2045第6.8节的规定,编码后的数据每隔76个字符就会换行,这在编写XML-RPC规范时是事实上的标准base64规范。

它还通过一种__cmp__()方法支持某些Python的内置操作符。

二进制对象的示例用法。我们将通过XMLRPC传输图像:

from SimpleXMLRPCServer import SimpleXMLRPCServer
import xmlrpclib

def python_logo():
     with open("python_logo.jpg", "rb") as handle:
         return xmlrpclib.Binary(handle.read())

server = SimpleXMLRPCServer(("localhost", 8000))
print "Listening on port 8000..."
server.register_function(python_logo, 'python_logo')

server.serve_forever()

客户端获取图像并将其保存到文件中:

import xmlrpclib

proxy = xmlrpclib.ServerProxy("http://localhost:8000/")
with open("fetched_python_logo.jpg", "wb") as handle:
    handle.write(proxy.python_logo().data)

5.故障对象

class xmlrpclib.Fault

一个Fault对象封装了XML-RPC错误标签的内容。故障对象具有以下属性:

faultCode

指示故障类型的字符串。

faultString

包含与故障关联的诊断消息的字符串。

在下面的例子中,我们将Fault通过返回一个复杂的类型对象来故意造成一个。服务器代码:

from SimpleXMLRPCServer import SimpleXMLRPCServer

# A marshalling error is going to occur because we're returning a
# complex number
def add(x, y):
    return x+y+0j

server = SimpleXMLRPCServer(("localhost", 8000))
print "Listening on port 8000..."
server.register_function(add, 'add')

server.serve_forever()

上述服务器的客户端代码:

import xmlrpclib

proxy = xmlrpclib.ServerProxy("http://localhost:8000/")
try:
    proxy.add(2, 5)
except xmlrpclib.Fault as err:
    print "A fault occurred"
    print "Fault code: %d" % err.faultCode
    print "Fault string: %s" % err.faultString

6. ProtocolError对象

class xmlrpclib.ProtocolError

ProtocolError对象描述底层传输层中的协议错误(例如404“未找到”错误,如果由URI指定的服务器不存在)。它具有以下属性:

url

触发错误的URI或URL。

errcode

错误代码。

errmsg

错误消息或诊断字符串。

headers

包含触发错误的HTTP / HTTPS请求标头的字符串。

在下面的例子中,我们将ProtocolError通过提供一个不指向XMLRPC服务器的URI 来故意引起:

import xmlrpclib

# create a ServerProxy with a URI that doesn't respond to XMLRPC requests
proxy = xmlrpclib.ServerProxy("http://www.google.com/")

try:
    proxy.some_method()
except xmlrpclib.ProtocolError as err:
    print "A protocol error occurred"
    print "URL: %s" % err.url
    print "HTTP/HTTPS headers: %s" % err.headers
    print "Error code: %d" % err.errcode
    print "Error message: %s" % err.errmsg

7. MultiCall对象

2.4版本中的新功能。

MultiCall对象提供了一种将多个调用封装到远程服务器到单个请求的方法[1]。

class xmlrpclib.MultiCall(server)

创建一个用于boxcar方法调用的对象。服务器是呼叫的最终目标。可以对结果对象进行调用,但它们会立即返回None,并只将MultiCall对象名称和参数存储在对象中。调用对象本身会导致所有存储的调用都作为单个system.multicall请求传输。这个调用的结果是一个发生器 ; 遍历这个生成器会产生单独的结果。

这个类的用法示例如下。服务器代码

from SimpleXMLRPCServer import SimpleXMLRPCServer

def add(x,y):
    return x+y

def subtract(x, y):
    return x-y

def multiply(x, y):
    return x*y

def divide(x, y):
    return x/y

# A simple server with simple arithmetic functions
server = SimpleXMLRPCServer(("localhost", 8000))
print "Listening on port 8000..."
server.register_multicall_functions()
server.register_function(add, 'add')
server.register_function(subtract, 'subtract')
server.register_function(multiply, 'multiply')
server.register_function(divide, 'divide')
server.serve_forever()

上述服务器的客户端代码:

import xmlrpclib

proxy = xmlrpclib.ServerProxy("http://localhost:8000/")
multicall = xmlrpclib.MultiCall(proxy)
multicall.add(7,3)
multicall.subtract(7,3)
multicall.multiply(7,3)
multicall.divide(7,3)
result = multicall()

print "7+3=%d, 7-3=%d, 7*3=%d, 7/3=%d" % tuple(result)

8.便利功能

xmlrpclib.boolean(value)

将任何Python值转换为其中一个XML-RPC布尔常量TrueFalse

xmlrpclib.dumps(params[, methodname[, methodresponse[, encoding[, allow_none]]]])

params转换为XML-RPC请求。或者如果方法响应为真,则将转换为响应。参数可以是参数的元组或Fault异常类的实例。如果methodresponse为true,则只能返回一个值,这意味着params的长度必须为1. 编码(如果提供)是在生成的XML中使用的编码; 默认是UTF-8。Python的None值不能用于标准的XML-RPC; 允许通过扩展来使用它,为allow_none提供一个真正的值。

xmlrpclib.loads(data[, use_datetime])

将XML-RPC请求或响应转换为Python对象,a (params, methodname)params是一个论元; methodname是一个字符串,或者None如果数据包中没有方法名称。如果XML-RPC数据包代表故障条件,则此函数将引发Fault异常。所述use_datetime标志可用于引起日期/时间值被表示为datetime.datetime对象; 这在默认情况下是错误的。

在版本2.5中更改:添加了use_datetime标志。

9.客户使用示例

# simple test program (from the XML-RPC specification)
from xmlrpclib import ServerProxy, Error

# server = ServerProxy("http://localhost:8000") # local server
server = ServerProxy("http://betty.userland.com")

print server

try:
    print server.examples.getStateName(41)
except Error as v:
    print "ERROR", v

要通过HTTP代理访问XML-RPC服务器,您需要定义一个自定义传输。以下示例显示了如何:

import xmlrpclib, httplib

class ProxiedTransport(xmlrpclib.Transport):
    def set_proxy(self, proxy):
        self.proxy = proxy

    def make_connection(self, host):
        self.realhost = host
        h = httplib.HTTPConnection(self.proxy)
        return h

    def send_request(self, connection, handler, request_body):
        connection.putrequest("POST", 'http://%s%s' % (self.realhost, handler))

    def send_host(self, connection, host):
        connection.putheader('Host', self.realhost)

p = ProxiedTransport()
p.set_proxy('proxy-server:8080')
server = xmlrpclib.ServerProxy('http://time.xmlrpc.com/RPC2', transport=p)
print server.currentTime.getCurrentTime()

10.客户端和服务器使用示例

请参阅SimpleXMLRPCServer示例。

1

这种方法首先在关于xmlrpc.com的讨论中提出。

扫码关注云+社区

领取腾讯云代金券