假设server端代码定义了一个RPC方法hello
import zerorpc class HelloRPC(object): def hello(self, name): return "Hello, %s" % name s = zerorpc.Server(HelloRPC()) s.bind("tcp://0.0.0.0:4242") s.run()
在客户端代码如果要调用只需简单新建一个Client实例,然后直接以client.hello()
调用。
import zerorpc client = zerorpc.Client() client.connect("tcp://127.0.0.1:4242") print client.hello("RPC")
Client作为一个通用类,并未定义def hello(name):
方法,直接以client.hello()
调用是怎么做到的?答案就是利用了python的__getattr__
和__call__
,关键代码如下。
class Client(object): def __init__(self, ): pass def __call__(self, method, *args, **kwargs): # 在这连接server,序列化参数,请求,反序列化响应数据,并return pass def __getattr__(self, method): # 返回一个闭包,该闭包封装了self和method. # 当这个闭包被执行时,即x(*args, **kwargs), # 即self(method, *args, **kargs)被运行, # 即self.__call__(self, method, *args, **kwargs) f = lambda *args, **kwargs: self(method, *args, **kwargs) return f
当执行client.hello('RPC')
时,会分两步,先获取hello这个属性的值,然后调用这个值。即先调用client.__getattr__('RPC')
查询hello这个属性的值,得到f,而f
是一个闭包函数,然后调用f('RPC')
。
The post zerorpc通用Client实例直接调用特定server RPC方法原理 appeared first on wingyiu.