很久之前的文章中提到过用RPyC进行进程间通信,
# 启动server,在rpyc/bin目录下
python rpyc_classic.py
# 客户端进行连接
import rpyc
conn = rpyc.classic.connect("localhost")
# 通过conn.modules访问server进程内的module
print conn.modules.sys
在Classic连接模式下,客户端代码可以访问到服务端的模块。这种连接方式暴露的内容过多,因此RPyC还有一种Service形式提供连接的方式。但Classic模式适用于什么场景呢?最近找到一个比较合适的情况,就是将其用于在多进程环境下进行调试连接,查看进程中的数据。
不过上面例子中的访问方式并没有那么方便,访问模块都需要从conn.modules中获取,有没有可能像导入本地模块一样导入远程模块?在阅读了Python PEP0302后,发现可以通过定制import流程来达到此功能。
以一个简单的例子来说明一下,定义RPyC Server端代码,
// foobar.py
from rpyc.core import SlaveService
from rpyc.utils.server import ThreadedServer
import threading
class Foobar(object):
pass
class RPyCThread(threading.Thread):
def run(self):
try:
server = ThreadedServer(SlaveService, port=18812, reuse_addr=True)
server.start()
except Exception as e:
print e
thread = RPyCThread()
thread.start()
在RPyC客户端代码中定制module加载过程,
class RpycLoader(object):
def __init__(self, host, port):
self.conn = None
self.port = port
self.host = host
def find_module(self, fullname, path=None):
return self
def load_module(self, full_name):
if self.conn is None:
self.conn = rpyc.classic.connect(self.host, self.port)
module = getattr(self.conn.modules, full_name, None)
return module
def connect(host, port):
sys.meta_path = [RpycLoader(host, port)]
在命令行中进入Python环境,首先连接RPyC,而后就能够将远程模块像本地模块那样导入,
import sys
connect('locast', 18812)
from foobar import Foobar