前言:
此刻大家对“python模块调用的用法”大体比较着重,看官们都需要了解一些“python模块调用的用法”的相关知识。那么小编也在网摘上网罗了一些有关“python模块调用的用法””的相关内容,希望姐妹们能喜欢,各位老铁们一起来了解一下吧!Python远程过程调用1.RPyc
RPyC(远程Python调用)是一个透明的Python库,用于对称的远程过程调用、集群和分布式计算。RPyC利用对象代理(object proxying,一种利用python动态特性的技术)来克服进程和计算机之间的物理界限,从而可以像本地对象一样操作远程对象。
2.安装
pip install rpyc3.RPyC编程模型
从RPyC 3.00开始,RPyC编程模型是基于服务的。服务提供了一种向另一方公开定义良好的功能集的方法,这使RPyC成为一个通用的RPC平台。示例如下:
import rpycclass MyService(rpyc.Service): def on_connect(self, conn): # code that runs when a connection is created # (to init the service, if needed) pass def on_disconnect(self, conn): # code that runs after the connection has already closed # (to finalize the service, if needed) pass def exposed_get_answer(self): # this is an exposed method return 42 exposed_the_real_answer_though = 43 # an exposed attribute def get_question(self): # while this method is not exposed return "what is the airspeed velocity of an unladen swallow?"
rpyc 4.0中添加了on_connect和on_disconnect的conn参数。
在上面的代码中,正如您所见,除了特殊的初始化 / 终结方法之外,您可以像其他任何类一样自由定义该类。但是,与常规类不同,您可以选择将哪些属性公开给另一方:如果名称以exposed_开头,则该属性将可以远程访问,否则只能在本地访问。在本例中,客户端可以调用get_-answer,但不能调用 get_question,稍后我们将看到这一点。
然而,要向世界公开您的服务,您需要启动一台服务器。有很多方法可以做到这一点,但最简单的是:
# ... continuing the code snippet from above ...if __name__ == "__main__": from rpyc.utils.server import ThreadedServer t = ThreadedServer(MyService, port=18861) t.start()
对于远程方,服务作为连接的根对象公开,例如conn.root。远程方调用示例如下:
>>> import rpyc>>> c = rpyc.connect("localhost", 18861)>>> c.root<__main__.MyService object at 0x834e1ac>
“根对象”是对服务器进程中的服务实例的引用。它可以用于访问和调用公开的属性和方法:
>>> c.root.get_answer()42>>> c.root.the_real_answer_though43
对于未公开的属性和方法:
>>> c.root.get_question()======= Remote traceback =======... File "/home/tomer/workspace/rpyc/core/protocol.py", line 298, in sync_request raise objAttributeError: cannot access 'get_question'3.1访问策略
默认情况下,只有当方法和属性以exposed_前缀开头时,它们才可见。这也意味着默认情况下无法访问列表或dict等内置对象的属性。如果需要,您可以通过在创建服务器时传递适当的选项来进行配置。例如:
from rpyc.utils.server import ThreadedServerserver = ThreadedServer(MyService, port=18861, protocol_config={ 'allow_public_attrs': True,})server.start()
有关所有可用设置的说明,请参阅默认配置:
参数
Default value
Description
allow_safe_attrs
True
是否允许使用safe属性
allow_exposed_attrs
True
是否允许公开属性(以'exposed_前缀'开头的属性)
allow_public_attrs
False
是否允许公共属性(不以“_”开头的属性)
allow_all_attrs
False
是否允许所有属性(包括私有)
safe_attrs
set([...])
被认为是安全的属性集
exposed_prefix
"exposed_"
暴露属性的前缀
allow_getattr
True
是否允许获取属性(getattr)
allow_setattr
False
是否允许设置属性(setattr)
allow_delattr
False
是否允许删除属性(delattr)
allow_pickle
False
是否允许使用“pickle”
include_local_traceback
True
是否在远程异常中包含本地回溯
instantiate_custom_exceptions
False
是否允许实例化自定义异常(不是内置异常)
import_custom_exceptions
False
是否允许从尚未导入的模块导入异常
instantiate_oldstyle_exceptions
False
是否允许实例化不是从“Exception”派生的异常。这不适用于Python 3及更高版本。
propagate_SystemExit_locally
False
是在本地传播“SystemExit”(终止服务器)还是向另一方传播(终止客户端)
propagate_KeyboardInterrupt_locally
False
是在本地传播“KeyboardInterrupt”(终止服务器)还是向另一方传播(终止客户端)
logger
None
用于记录异常(在发送给另一方之前)和其他事件的日志实例。如果“无”,则不会进行日志记录。
connid
None
运行时:RPyC连接ID(主要用于调试目的)
credentials
None
运行时: 服务器的[authenticator]返回的credentails对象
endpoints
None
运行时: 连接的端点。这是一个由本地套接字端点(getsockname)和远程套接字端点(getpeername)组成的元组。这由服务器在接受连接时设置;客户端连接没有设置此配置选项。
sync_request_timeout
30
等待结果的默认超时
3.2共享服务实例
请注意,我们在这里将类MyService传递给服务器,其效果是每个传入连接都将使用自己的独立MyService实例作为根对象。如果您传入一个实例,所有传入的连接都将使用该实例作为其共享根对象,例如:
t = ThreadedServer(MyService(), port=18861)
从rpyc 4.0开始,支持传递实例。在早期版本中,您只能传递一个类,其中每个连接将接收一个单独的实例。
3.3向服务传递参数
在第二种情况下,传入一个完全构造的服务实例,向_init__函数传递额外的参数是很简单的。但是,如果要在分离每个连接的根对象的同时传递参数,则情况会稍微复杂一些。在本例中,使用classpartial()如下:
from rpyc.utils.helpers import classpartialservice = classpartial(MyService, 1, 2, pi=3)t = ThreadedServer(service, port=18861)
classpartial是在4.0版中添加的。
3.4服务名称
所有服务都有一个名称,通常是类的名称,减去“服务”后缀。在我们的例子中,服务名称是“MY”(服务名称不区分大小写)。如果要定义自定义名称或多个名称(别名),可以通过设置别名列表来定义。第一个别名被认为是“正式名称”,而其他别名是:
class MyService(rpyc.Service): ALIASES = ["floop", "bloop"] ...
在原始代码片段中,客户机得到的是:
>>> c.root.get_service_name()'MY'>>> c.root.get_service_aliases()('MY',)
服务具有名称的原因是服务注册表:通常情况下,服务器会将其详细信息广播到附近的注册表服务器以供发现。要使用服务发现,请确保启动 bin/rpyc_registry.py 。该服务器监听广播UDP套接字,并将回答有关哪些服务在何处运行的查询。
一旦注册服务器在网络上的某个“可广播”位置运行,并且服务器配置为自动注册(默认设置),客户端就可以自动发现服务。要启动服务器,请执行以下操作:
>>> mysvc = rpyc.OneShotServer(service=MyService, port=18861, auto_register=True)>>> mysvc.start()
要查找运行给定服务名称的服务器,请执行以下操作:
>>> rpyc.list_services()>>> rpyc.discover("MY")(('192.168.1.101', 18861),)
如果您不关心连接到哪个服务器,请使用connect_by_service:
>>> c2 = rpyc.connect_by_service("MY")>>> c2.root.get_answer()423.5解耦服务
到目前为止,我们只讨论了服务器公开的服务,但是客户端呢?客户端是否也公开了服务?毕竟,RPyC是一个对称协议——客户端和服务器之间没有区别。正如您可能已经猜到的,答案是肯定的:客户端和服务器都公开服务。然而,双方公开的服务不一定是相同的——它们是解耦的。
默认情况下,客户端(使用connect()函数连接到服务器)公开VoidService。顾名思义,该服务不向另一方公开任何功能,这意味着服务器不能向客户端发出请求(除了显式传递的功能,如函数回调)。通过将service=参数传递给connect()函数,可以设置客户端公开的服务。
连接两端的服务是解耦的,这并不意味着它们可以是任意的。例如,“服务A”可能会连接到“服务B”——如果不是这样,就会出现运行时错误(主要是AttributeError)。很多时候,两端的服务可能不同,但请记住,如果需要双方之间的交互,两个服务必须“兼容”。
标签: #python模块调用的用法