12.11.6 分派调用
默认地,register_instance()会查找实例的所有可调用属性(属性名以一个下划线(_)开头的除外),并用它们的名字注册。为了更谨慎地处理公布的方法。可以使用定制的分派逻辑。
from xmlrpc.server import SimpleXMLRPCServer
import os
import inspect
server = SimpleXMLRPCServer(
('localhost',9000),
logRequests=True,
)
def expose(f):
"Decorator to set exposed flag on a function."
f.exposed = True
return f
def is_exposed(f):
"Test whether another function should be publicly exposed."
return getattr(f,'exposed',False)
class MyService:
PREFIX = 'prefix'
def _dispatch(self,method,params):
# Remove our prefix from the method name.
if not method.startswith(self.PREFIX + '.'):
raise Exception(
'method "{}" is not supported'.format(method)
)
method_name = method.partition('.')[2]
func = getattr(self,method_name)
if not is_exposed(func):
raise Exception(
'method "{}" is not supported'.format(method)
)
return func(*params)
@expose
def public(self):
return 'This is public'
def private(self):
return 'This is private'
server.register_instance(MyService())
try:
print('Use Control-C to exit')
server.serve_forever()
except KeyboardInterrupt:
print('Exiting')
MyServeice的public()方法被标记为要公布到XNL-RPC服务,而private()方法不公布。在客户试图访问MyService中的一个函数时会调用_dispatch()方法。它首先强调使用一个前缀(在这里是prefix.,不过也可以使用任意的串)。然后要求这个函数有个名为exposed的属性,而且值为True。为方便起见,这里使用一个修饰符为函数设置这个exposed标志。下面的例子包含了一些示例客户调用。
import xmlrpc.client
proxy = xmlrpc.client.ServerProxy('http://localhost:9000')
print('public():',proxy.prefix.public())
try:
print('private():',proxy.prefix.private())
except Exception as err:
print('\nERROR:',err)
try:
print('public() without prefix:',proxy.public())
except Exception as err:
print('\nERROR:',err)
下面给出得到的输出,这里捕获并报告了预料之中的错误消息。
还有另外一些方法可以覆盖分派机制,包括直接从SimpleXMLRPCServer源生子类。参考这个模块中的docstring来了解更多详细内容。