【译】Python rpyc官方文档

本文档详细介绍了 RPyC 的使用,包括如何启动服务器和客户端,访问远程模块和内建函数,利用 eval 和 execute 方法执行远程代码,以及 teleport 方法的运用。此外,还探讨了网络引用、异常处理,以及服务和新形式的 RPyC,如服务的访问策略、共享服务实例和参数传递。最后,讲解了回调、对称性和异步操作与事件处理,展示了 RPyC 在远程调用和事件监听中的强大功能。
摘要由CSDN通过智能技术生成

第一部分: 经典 RPyC 简介

我们将从经典的 RPyC 来开始我们的教程, 即 RPyC 2.60 的方法学。 因为 RPyC 3 版本对整个库做了重新设计, 所以有了些改变, 但是如果您对 RPyC 2.60 很熟悉, 您会有宾至如归的感觉。 如果您不熟悉, 我们保证您过一会也会有宾至如归的感觉。

1、运行一个服务器

让我们从基础开始 ———— 运行一个服务器。 在本教程中, 我们会将服务器和客户端运行在同一个机器上(localhost)。 经典的服务器可以使用下面的命令开启:

$ python bin/rpyc_classic.py
INFO:SLAVE/18812:server started on [127.0.0.1]:18812

下面展示了服务器正在运行时的参数:

  • “SLAVE” 表明了 “slaveService” (您稍后将会学到更多关于服务的知识), “[127.0.0.1]:18812” 是服务器绑定的地址, 在这个例子中, 服务器只接受来自于本机的连接。 如果您使用 “–host 0.0.0.0” 来启动一个服务器, 您将可以从任何地方来执行任何代码。

2、运行一个客户端

下一步是运行一个连接到服务器的一个客户端。 被用来创建一个连接到服务器的代码非常简单, 您会同意的:

import rpyc

conn = rpyc.classic.connect("localhost")

如果您的服务器没有在默认的端口上运行(TCP 18812), 您需要传入 “port=” 参数给 “classic.connect()”。

3、modules 的命名空间

连接对象的 modules 属性暴露的服务器的 module-space, 即它允许您进入远程模块。 下面是如何去做的方式:

rsys = conn.modules.sys # 服务器上的远程模块

这个点符号仅适用于顶层的模块。 每当您要对一个包中包含的模块进行嵌套导入时, 您必须使用括号符号来导入远程模块, 比如:

minidom = conn.modules["xml.dom.minidom"]

有了这个, 您几乎可以做任何事情。 举个例子, 这是您如何看服务器的命令行:

>>> rsys.argv
["bin/rpyc_classic.py"]

为服务器的导入机制添加模块搜索路径:

>>> rsys.path.append("/tmp/totally-secure-package-location")

改变服务器进程的当前工作目录:

>>> conn.modules.os.chdir("..")

或者甚至在服务器的标准输出中打印一些东西:

>>> print("Hello World", file=conn.modules.sys.stdout())

4、builtins 的命名空间

经典连接的 “builtins” 属性暴露了所有在服务器的 Python 环境中可使用的内建函数。 举个例子, 您可以用它来进入服务器上的一个文件:

>>> f = conn.builtins.open("/home/oblivious/.ssh/id_rsa")
>>> f.read()
'-----BEGIN RSA PRIVATE KEY-----\nMIIJKQIBAAKCAgEA0...XuVmz/ywq+5m\n-----END RSA PRIVATE KEY-----\n'

哎呀, 我刚刚泄露了我的私钥…

5、eval 和 execute 方法

如果您还没有满足, 接下来还有更多的: 经典连接也具有 eval 和 execute 属性, 他们允许您在服务器上求出任意表达式的值甚至执行任意的语句。 举个例子:

>>> conn.execute('import math')
>>> conn.eval('2 * math.pi')
6.283185307179586

但是, 这需要 RPyC 经典连接具有一些全局变量的概念, 您如何能看到它们? 它们可以通过 “namespace” 属性访问 ———— 每个新连接都会初始化该属性为一个空字典。 所以, 当我们导入之后, 我们现在可以:

>>> conn.namespace
{'__builtins__': <...>, 'math': <...>}

一些敏锐的读者可能会注意到上面的诡计都不是严格需要的, 因为使用 “conn.builtins.compile()” 方法 ———— 可以通过 “conn.modules.builtins.compile()” 方法访问到, 利用远程创建的字典手动提供该函数可以实现同样的功能。

这是真的, 但是有时我们需要一点糖。

6、teleport 方法

这有一个很有意思的方法, 它允许您传输一个方法到另一边, 并且在那里执行它们:

>>> def square(x):
...    return x ** 2
>>> fn = conn.teleport(square)
>>> fn(2)

这个期望计算 2 的平方, 当时这个计算是在远程执行的!

而且, 这种传输的方法是在远程命名空间中自动定义的:

>>> conn.eval('square(3)')
9

>>> conn.namespace['square'] is fn
True

并且传输的代码同样可以访问命名空间:

>>> con.execute('import sys')
>>> conn.teleport(lambda: print(sys.version_info))

在远程的终端中打印版本信息。

请注意, 当前它不可能支持传输任意的函数, 特别是闭包对象可能会出问题。 当出现问题时, 查看一下外部库可能是值得的, 比如 dill 库。

第二部分: 网络参考和异常

在第一部分中, 我们了解了如何使用 RPyC 经典连接来远程执行几乎所有事情。

目前一切看起来都很正常。 现在是时候弄脏我们的手, 来进一步理解引擎盖下到底发生了什么!

1. 设置

开启一个经典服务器使用:

python bin/rpyc_classic.py

连接好您的客户端:

>>> import rpyc
>>> conn = rpyc.classic.connect("localhost")

2. 网络引用(Netrefs)

我们知道我们可以使用 “conn.modules.sys” 来访问服务器上的 “sys” 模块。 但是那到底是什么神奇的东西呢?


                
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值