不同进程间进行通讯的方式很多,对于Python实现的系统来说,如果想通过RPC方式进行通讯,那么可以考虑选用 RPyC 这个框架。

安装RPyC

RPyC可以通过pip直接进行安装,

pip install rpyc

两种启动模式

RPC操作需要掉用方与被调用方,在RPyC里面需要启动对应的Server,Client在连接上Server之后,双方可以互相调用。

classic

RPyC经典启动模式中,进程之间完全“信任”,可以直接调用进程上的方法。


# 启动server,在rpyc/bin目录下
python rpyc_classic.py

# 客户端进行连接
import rpyc
conn = rpyc.classic.connect("localhost")

# 通过conn.modules访问server进程内的module
print conn.modules.sys

service

RPyC新版里面提供了另外一种Server启动模式,服务端通过定义Service类来向Client暴露接口。

Server端代码,exposed_前缀申明的成员函数可以被Client直接访问。

# -*- encoding:utf-8 -*-

from rpyc.utils.classic import SlaveService
from rpyc.utils.server import ThreadedServer

class ServerService(SlaveService):
    def on_connect(self):
        print 'on_connect'

    def on_disconnect(self):
        print 'on_disconnect'

    def exposed_get_answer(self):
        return 42

if __name__ == '__main__':
    server = ThreadedServer(ServerService, port=18861, hostname="0.0.0.0")
    server.start()

对应的Client代码,

conn = rpyc.connect('127.0.0.1', 18861, config={'allow_all_attrs': True})
conn.root.get_answer()

数据传递

Client与Server之间调用函数时可以像调用本地函数一样直接传递各种参数。不过需要注意的是传递过去后接收方拿到的数据类型。Theory of Operation 这个文档里面介绍了,在RPyC调用过程中,数据通过两种方式进行传递,

  • By Value。简单的内置类型等通过By Value方式进行传递。
  • By Reference。其余对象类型同过By Reference方式进行传递。接收方实际获取到的数据类型为netref (network reference)。

对于By Reference传递过来的对象,在一些处理上要特别注意,避免因为实际对象类型是netref造成的问题。