gpt4 book ai didi

python - 如何在 Pyro v.4.63 中正确使用第三方库

转载 作者:行者123 更新时间:2023-12-01 02:25:13 25 4
gpt4 key购买 nike

我对使用远程第三方库有点困惑:

1) 例如,我有服务器代码:

import Pyro4
import Pyro4.naming
import Pyro4.utils.flame
Pyro4.config.REQUIRE_EXPOSE = False
Pyro4.config.FLAME_ENABLED = True
Pyro4.config.SERIALIZERS_ACCEPTED = set(["pickle"])
Pyro4.config.SERIALIZER = 'pickle' # for flameserver


def _main():
"""Start RPC server."""
ip_address = Pyro4.socketutil.getIpAddress(None, workaround127=True)
ns_daemon = Pyro4.naming.NameServerDaemon(host=ip_address, port=RPC_PORT)
Pyro4.utils.flame.start(ns_daemon)

from remote_management.rpc.component.shell import Shell
shell_uri = ns_daemon.register(Shell())
ns_daemon.nameserver.register("shell", shell_uri)
from remote_management.rpc.component.cpu import CPU
cpu_uri = ns_daemon.register(CPU())
ns_daemon.nameserver.register("cpu", cpu_uri)

ns_daemon.requestLoop()
ns_daemon.close()

if __name__ == "__main__":
_main()

CPU组件是这样的:

import psutil

class CPU(object):
def ps(self):
return psutil.cpu_times()

当我在客户端中使用它时,如下所示:

import Pyro4
import Pyro4.utils.flame
import Pyro4.errors

Pyro4.config.SERIALIZER = "pickle"

proxy = Pyro4.Proxy("PYRONAME:cpu@myhost:47976")
print proxy.ps()

我收到错误:

Traceback (most recent call last):
File "t.py", line 145, in <module>
print proxy.ps()
File "/home/korolev/.envs/auto/lib/python2.7/site-packages/Pyro4/core.py", line 187, in __call__
return self.__send(self.__name, args, kwargs)
File "/home/korolev/.envs/auto/lib/python2.7/site-packages/Pyro4/core.py", line 464, in _pyroInvoke
data = serializer.deserializeData(msg.data, compressed=msg.flags & message.FLAGS_COMPRESSED)
File "/home/korolev/.envs/auto/lib/python2.7/site-packages/Pyro4/util.py", line 170, in deserializeData
return self.loads(data)
File "/home/korolev/.envs/auto/lib/python2.7/site-packages/Pyro4/util.py", line 451, in loads
return pickle.loads(data)

ImportError: No module named psutil._pslinux

如您所见,它无法反序列化。如果我将返回更改为:

返回元组(psutil.cpu_times()),然后就可以了。

2)我认为下一个问题具有相同的性质:除了组件之外,服务器代码几乎相同

from remote_management.rpc.component.registrator import ModuleRegistrator
reg_uri = ns_daemon.register(ModuleRegistrator())
ns_daemon.nameserver.register("module_registrator", reg_uri)

如果我需要远程模块,但本地没有,为什么我不能这样做:

注册器组件:

class ModuleRegistrator(object):
def register(self, module):
module = importlib.import_module(module)
self._pyroDaemon.register(module)
return module

所以当我在客户端使用它时:

proxy = Pyro4.Proxy("PYRONAME:module_registrator@myhost:47976")
print proxy.register("psutil").cpu_times()

我收到错误:

Traceback (most recent call last):
File "t.py", line 145, in <module>
print proxy.register('psutil').cpu_times()
File "/home/korolev/.envs/auto/lib/python2.7/site-packages/Pyro4/core.py", line 279, in __getattr__
raise AttributeError("remote object '%s' has no exposed attribute or method '%s'" % (self._pyroUri, name))
AttributeError: remote object 'PYRONAME:module_registrator@myhost:47976' has no exposed attribute or method 'register'

请帮助我理解这个错误以及我在哪里遗漏了什么?与第三方远程合作时处理此类问题的最佳方法是什么?提前致谢!

最佳答案

首先,您似乎正在使用 Pyro4 的“flame”功能,它需要 pickle 序列化协议(protocol)。这很强大,但也并非没有问题。您确定要/需要使用火焰吗?我希望您了解其安全隐患。 http://pyro4.readthedocs.io/en/latest/flame.html

现在,您的实际问题由三个部分组成(尝试使您以后的问题更多地涉及单个问题,这使得回答它们变得更加简单)

回答问题的第一部分:

正如您自己已经发现的那样,您不能假设所有类型都可以通过网络传输并神奇地在另一端工作。特别是对于 pickle ,这仅在模块所在的情况下才有效类型已定义,双方都可用。在您的情况下,似乎 psutil 模块在您的客户端不可用,因此当它尝试反序列化 psutil.cpu_times() 返回的对象时会出现 pickle 错误.

解决方案可能是在客户端也安装 psutil。您还发现了一种替代解决方案:不要通过线路传递自定义类型的对象,而是尽可能坚持使用内置类型。当您将结果转换为元组或列表或字典时,这些可以序列化和反序列化,没有任何问题(如果它们包含的所有对象也是内置类型)。

回答问题的第二部分:

此代码看起来您​​正在尝试为第一个问题中的问题找到解决方法?无论如何,错误应该是清楚的;这意味着它所说的:您的代理连接到的远程对象没有公开您尝试调用的方法。您应该添加一个 @Pyro4.expose 装饰正确地暴露它。

也就是说,您已经在使用 Flame,那么为什么不使用它的远程模块功能呢?请参阅http://pyro4.readthedocs.io/en/latest/flame.html#flame-object-and-examples

例如(我假设您在客户端安装了 psutil):

import Pyro4.utils.flame

Pyro4.config.SERIALIZER = "pickle"
flame = Pyro4.utils.flame.connect("yourhost:9999")

psutilmodule = flame.module("psutil")
print("remote cpu:", psutilmodule.cpu_times())

最后,

解决您的问题“与第三方远程合作时处理此类问题的最佳方法是什么”:

  • 尽量不要公开您正在使用的 API 的详细信息和类型,尽可能将其减少为内置类型。 http://pyro4.readthedocs.io/en/latest/tipstricks.html#consider-using-basic-data-types-instead-of-custom-classes如果你做得正确,你也可以简单地使用 Pyro 的默认序列化器(serpent)而不是 pickle,并且不会有任何安全问题。 (这确实需要一个不依赖火焰的解决方案,请参阅下一个项目符号)
  • 不要使用 Flame,除非您完全确定您可以接受其安全隐患并且无法通过其他方式解决您的问题。相反,使用您自己编写的专用自定义 API 创建一个普通的 Pyro 服务器类。
  • 仅公开您实际需要远程访问的远程方法。

关于python - 如何在 Pyro v.4.63 中正确使用第三方库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47486024/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com