zerorpc for python

Overview

zerorpc

https://travis-ci.org/0rpc/zerorpc-python.svg?branch=master

Mailing list: [email protected] (https://groups.google.com/d/forum/zerorpc)

zerorpc is a flexible RPC implementation based on zeromq and messagepack. Service APIs exposed with zerorpc are called "zeroservices".

zerorpc can be used programmatically or from the command-line. It comes with a convenient script, "zerorpc", allowing to:

  • expose Python modules without modifying a single line of code,
  • call those modules remotely through the command line.

Installation

On most systems, its a matter of:

$ pip install zerorpc

Depending of the support from Gevent and PyZMQ on your system, you might need to install libev (for gevent) and libzmq (for pyzmq) with the development files.

Create a server with a one-liner

Let's see zerorpc in action with a simple example. In a first terminal, we will expose the Python "time" module:

$ zerorpc --server --bind tcp://*:1234 time

Note

The bind address uses the zeromq address format. You are not limited to TCP transport: you could as well specify ipc:///tmp/time to use host-local sockets, for instance. "tcp://*:1234" is a short-hand to "tcp://0.0.0.0:1234" and means "listen on TCP port 1234, accepting connections on all IP addresses".

Call the server from the command-line

Now, in another terminal, call the exposed module:

$ zerorpc --client --connect tcp://127.0.0.1:1234 strftime %Y/%m/%d
Connecting to "tcp://127.0.0.1:1234"
"2011/03/07"

Since the client usecase is the most common one, "--client" is the default parameter, and you can remove it safely:

$ zerorpc --connect tcp://127.0.0.1:1234 strftime %Y/%m/%d
Connecting to "tcp://127.0.0.1:1234"
"2011/03/07"

Moreover, since the most common usecase is to connect (as opposed to bind) you can also omit "--connect":

$ zerorpc tcp://127.0.0.1:1234 strftime %Y/%m/%d
Connecting to "tcp://127.0.0.1:1234"
"2011/03/07"

See remote service documentation

You can introspect the remote service; it happens automatically if you don't specify the name of the function you want to call:

$ zerorpc tcp://127.0.0.1:1234
Connecting to "tcp://127.0.0.1:1234"
tzset       tzset(zone)
ctime       ctime(seconds) -> string
clock       clock() -> floating point number
struct_time <undocumented>
time        time() -> floating point number
strptime    strptime(string, format) -> struct_time
gmtime      gmtime([seconds]) -> (tm_year, tm_mon, tm_mday, tm_hour, tm_min,
mktime      mktime(tuple) -> floating point number
sleep       sleep(seconds)
asctime     asctime([tuple]) -> string
strftime    strftime(format[, tuple]) -> string
localtime   localtime([seconds]) -> (tm_year,tm_mon,tm_mday,tm_hour,tm_min,

Specifying non-string arguments

Now, see what happens if we try to call a function expecting a non-string argument:

$ zerorpc tcp://127.0.0.1:1234 sleep 3
Connecting to "tcp://127.0.0.1:1234"
Traceback (most recent call last):
[...]
TypeError: a float is required

That's because all command-line arguments are handled as strings. Don't worry, we can specify any kind of argument using JSON encoding:

$ zerorpc --json tcp://127.0.0.1:1234 sleep 3
Connecting to "tcp://127.0.0.1:1234"
[wait for 3 seconds...]
null

zeroworkers: reversing bind and connect

Sometimes, you don't want your client to connect to the server; you want your server to act as a kind of worker, and connect to a hub or queue which will dispatch requests. You can achieve this by swapping "--bind" and "--connect":

$ zerorpc --bind tcp://*:1234 strftime %Y/%m/%d

We now have "something" wanting to call the "strftime" function, and waiting for a worker to connect to it. Let's start the worker:

$ zerorpc --server tcp://127.0.0.1:1234 time

The worker will connect to the listening client and ask him "what should I do?"; the client will send the "strftime" function call; the worker will execute it and return the result. The first program will display the local time and exit. The worker will remain running.

Listening on multiple addresses

What if you want to run the same server on multiple addresses? Just repeat the "--bind" option:

$ zerorpc --server --bind tcp://*:1234 --bind ipc:///tmp/time time

You can then connect to it using either "zerorpc tcp://*:1234" or "zerorpc ipc:///tmp/time".

Wait, there is more! You can even mix "--bind" and "--connect". That means that your server will wait for requests on a given address, and connect as a worker on another. Likewise, you can specify "--connect" multiple times, so your worker will connect to multiple queues. If a queue is not running, it won't affect the worker (that's the magic of zeromq).

Warning

A client should probably not connect to multiple addresses!

Almost all other scenarios will work; but if you ask a client to connect to multiple addresses, and at least one of them has no server at the end, the client will ultimately block. A client can, however, bind multiple addresses, and will dispatch requests to available workers. If you want to connect to multiple remote servers for high availability purposes, you insert something like HAProxy in the middle.

Exposing a zeroservice programmatically

Of course, the command-line is simply a convenience wrapper for the zerorpc python API. Below are a few examples.

Here's how to expose an object of your choice as a zeroservice:

class Cooler(object):
    """ Various convenience methods to make things cooler. """

    def add_man(self, sentence):
        """ End a sentence with ", man!" to make it sound cooler, and
        return the result. """
        return sentence + ", man!"

    def add_42(self, n):
        """ Add 42 to an integer argument to make it cooler, and return the
        result. """
        return n + 42

    def boat(self, sentence):
        """ Replace a sentence with "I'm on a boat!", and return that,
        because it's cooler. """
        return "I'm on a boat!"

import zerorpc

s = zerorpc.Server(Cooler())
s.bind("tcp://0.0.0.0:4242")
s.run()

Let's save this code to cooler.py and run it:

$ python cooler.py

Now, in another terminal, let's try connecting to our awesome zeroservice:

$ zerorpc -j tcp://localhost:4242 add_42 1
43
$ zerorpc tcp://localhost:4242 add_man 'I own a mint-condition Volkswagen Golf'
"I own a mint-condition Volkswagen Golf, man!"
$ zerorpc tcp://localhost:4242 boat 'I own a mint-condition Volkswagen Golf, man!'
"I'm on a boat!"

Congratulations! You have just made the World a little cooler with your first zeroservice, man!

Comments
  • zerorpc not working on CentOs7

    zerorpc not working on CentOs7

    Hi, I'm new user and try to use zerorpc on CentOS7. On Ubuntu same code work great.

    python2.7 -V: Python 2.7.9 Metadata-Version: 2.0 Name: zerorpc Version: 0.5.2 Summary: zerorpc is a flexible RPC based on zeromq. Home-page: https://github.com/0rpc/zerorpc-python Author: François-Xavier Bourlet [email protected]. Author-email: UNKNOWN License: MIT Location: /usr/local/lib/python2.7/site-packages

    Metadata-Version: 2.0 Name: gevent Version: 1.0.2 Summary: Coroutine-based network library Home-page: http://www.gevent.org/ Author: Denis Bilenko Author-email: [email protected] License: UNKNOWN Location: /usr/local/lib/python2.7/site-packages

    Metadata-Version: 2.0 Name: pyzmq Version: 15.1.0 Summary: Python bindings for 0MQ Home-page: https://pyzmq.readthedocs.org Author: Brian E. Granger, Min Ragan-Kelley Author-email: [email protected] License: LGPL+BSD Location: /usr/local/lib/python2.7/site-packages

    Metadata-Version: 2.0 Name: msgpack-python Version: 0.4.6 Summary: MessagePack (de)serializer. Home-page: http://msgpack.org/ Author: INADA Naoki Author-email: [email protected] License: UNKNOWN Location: /usr/local/lib/python2.7/site-packages

    Code Server: class channelRPCServer(object): def test(self, name): return "Test done. Received text, %s" % name

    server = zerorpc.Server(channelRPCServer()) server.bind("tcp://0.0.0.0:4242") print "RPC Server binded" server.run()

    Client cli: zerorpc tcp://127.0.0.1:4242 test RPC

    Please help. Thanks

    opened by Olmer1st 19
  • How keep alive a client?

    How keep alive a client?

    I'm building a service that (crons) that could take hours/day before activate a client. So for the majority of the time, the client(s) will be waiting for a job.

    How can I keep alive the client, and still get new task for a server when ready?

    Think in something like pubnub.com

    opened by mamcx 19
  • Add authentication support

    Add authentication support

    I'm not quite sure if this patch should be merged. But I'd like to bring up a discussion about whether should zerorpc have authentication support built-in.

    The need of authentication support start from day one when I use zerorpc to build some internal service since I have to expose this service to the internet.

    When I heard the release of stack.io, I though I might use stack.io as a gateway doing the authentication work. But I couldn't find the authentication method for clients connected through zerorpc.

    So I begin to add authentication support by myself.

    This patch consists two commits. The first one patches current zerorpc code base to support custom Event class for Server and Client. And the second one add signed requests based authentication using custom Event class and proper middleware.

    When I was modifying current zerorpc code base, I tried to change as less as possible and I put authentication related code in a separate file as kind of extension.

    Here are some example code shows about how to use authentication:

    # server
    import time
    import zerorpc
    from zerorpc.auth import SignedEvent, SharedSecretMiddleware
    
    zerorpc.Context.get_instance().register_middleware(SharedSecretMiddleware('some_random_key'))
    server = zerorpc.Server(time, event_class=SignedEvent)
    server.bin("tcp://0.0.0.0:4242")
    server.run()
    
    # client
    import zerorpc
    from zerorpc.auth import SignedEvent, SharedSecretMiddleware
    
    zerorpc.Context.get_instance().register_middleware(SharedSecretMiddleware('some_random_key'))
    client = zerorpc.Client(event_class=SignedEvent)
    client.connect('tcp://127.0.0.1:4242')
    print client.strftime('%Y/%m/%d')
    

    I don't know the design decisions about authentication. If we decided not to include authentication in zerorpc, could we just merge the first commit and give the developers ability to change the default behavior of events so that they could implement their own authentication mechanism in their own code base?

    Btw, I really enjoyed writing services with zerorpc. Thank you for this wonderful project.

    opened by adieu 16
  • msgpack Error

    msgpack Error

    Hi, I followed the doc from http://www.zerorpc.io/

    after pip install zererpc,I wrote the 'Hello World' Server and Client example on two different Linux Server.

    and I got this from Server

    # python s.py 
    ERROR:zerorpc.channel:zerorpc.ChannelMultiplexer ignoring error on recv
    Traceback (most recent call last):
      File "/usr/lib/python2.6/site-packages/zerorpc/channel.py", line 79, in _channel_dispatcher
        event = self._events.recv()
      File "/usr/lib/python2.6/site-packages/zerorpc/events.py", line 332, in recv
        event = Event.unpack(blob)
      File "/usr/lib/python2.6/site-packages/zerorpc/events.py", line 188, in unpack
        unpacker.feed(blob)
      File "msgpack/_unpacker.pyx", line 318, in msgpack._unpacker.Unpacker.feed (msgpack/_unpacker.cpp:318)
    TypeError: 'Frame' does not have the buffer interface
    ERROR:zerorpc.channel:zerorpc.ChannelMultiplexer ignoring error on recv
    

    here is the code:

    #Server
    import zerorpc
    
    class HelloRPC(object):
        def hello(self, name):
            return "Hello, %s" % name
    
    s = zerorpc.Server(HelloRPC())
    s.bind("tcp://0.0.0.0:1234")
    s.run()
    
    #Client
    import zerorpc
    
    client = zerorpc.Client()
    client.connect("tcp://172.16.200.84:1234")
    print(client.hello("World"))
    

    I'am a new user,What did I miss?

    opened by liuyangc3 15
  • LostRemote exceptions while using gevent.zeorpc

    LostRemote exceptions while using gevent.zeorpc

    We've been experiencing issues with zerorpc and gevent.subprocess.

    Consider the following test:

    from unittest import TestCase
    from time import time
    from gevent import spawn, sleep, event
    from gevent.subprocess import Popen
    from zerorpc import Server, Client
    
    
    class Service(object):
        def get_nothing(self):
            pass
    
    
    class BackgroundJobTestCase(TestCase):
        def setUp(self):
            self.stop_event = event.Event()
            self.background_job = spawn(self._start_job)
    
        def _start_job(self):
            while not self.stop_event.is_set():
                Popen("sleep 1", shell=True).wait()  # this does not work
                # sleep(1)  # this works
    
        def tearDown(self):
            self.stop_event.set()
            self.background_job = self.background_job.join()
    
        def test_rpc_with_background_job_for_longer_periods(self, duration_in_seconds=600):
            server = Server(Service())
            server.bind("tcp://0.0.0.0:7001")
            server._acceptor_task = spawn(server._acceptor)  # do not worry about teardown - the test fails in the middle
            client = Client()
            client.connect("tcp://0.0.0.0:7001")
            start_time = time()
            while abs(time() - start_time) <= duration_in_seconds:
                client.get_nothing()
    

    Running this on CentOS 6.4 fails with:

    bin/nosetests tests/long_tests/zerorpc_and_subprocess.py                   13-06-04 19:50
    Traceback (most recent call last):
      File "/root/mainline/eggs/gevent-1.0rc2-py2.7-linux-x86_64.egg/gevent/greenlet.py", line 328, in run
        result = self._run(*self.args, **self.kwargs)
      File "/root/mainline/eggs/zerorpc-0.4.1.2-py2.7.egg/zerorpc/events.py", line 63, in _sender
        self._socket.send(parts[-1])
      File "/root/mainline/eggs/zerorpc-0.4.1.2-py2.7.egg/zerorpc/gevent_zmq.py", line 104, in send
        self._on_state_changed()
      File "/root/mainline/eggs/zerorpc-0.4.1.2-py2.7.egg/zerorpc/gevent_zmq.py", line 72, in _on_state_changed
        events = self.getsockopt(_zmq.EVENTS)
      File "socket.pyx", line 388, in zmq.core.socket.Socket.get (zmq/core/socket.c:3713)
      File "checkrc.pxd", line 21, in zmq.core.checkrc._check_rc (zmq/core/socket.c:5859)
    ZMQError: Interrupted system call
    <Greenlet at 0x284c5f0: <bound method Sender._sender of <zerorpc.events.Sender object at 0x2864a50>>> failed with ZMQError
    
    E
    ======================================================================
    ERROR: test_rpc_with_background_job_for_longer_periods (zerorpc_and_subprocess.BackgroundJobTestCase)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "/root/mainline/tests/long_tests/zerorpc_and_subprocess.py", line 37, in test_rpc_with_background_job_for_longer_periods
        client.get_nothing()
      File "/root/mainline/eggs/zerorpc-0.4.1.2-py2.7.egg/zerorpc/core.py", line 256, in <lambda>
        return lambda *args, **kargs: self(method, *args, **kargs)
      File "/root/mainline/eggs/zerorpc-0.4.1.2-py2.7.egg/zerorpc/core.py", line 241, in __call__
        return self._process_response(request_event, bufchan, timeout)
      File "/root/mainline/eggs/zerorpc-0.4.1.2-py2.7.egg/zerorpc/core.py", line 213, in _process_response
        reply_event = bufchan.recv(timeout)
      File "/root/mainline/eggs/zerorpc-0.4.1.2-py2.7.egg/zerorpc/channel.py", line 262, in recv
        event = self._input_queue.get(timeout=timeout)
      File "/root/mainline/eggs/gevent-1.0rc2-py2.7-linux-x86_64.egg/gevent/queue.py", line 200, in get
        result = waiter.get()
      File "/root/mainline/eggs/gevent-1.0rc2-py2.7-linux-x86_64.egg/gevent/hub.py", line 568, in get
        return self.hub.switch()
      File "/root/mainline/eggs/gevent-1.0rc2-py2.7-linux-x86_64.egg/gevent/hub.py", line 331, in switch
        return greenlet.switch(self)
    LostRemote: Lost remote after 10s heartbeat
    
    ----------------------------------------------------------------------
    Ran 1 test in 102.469s
    
    FAILED (errors=1)
    

    with gevent-1.0rc2 and zerorpc-0.4.1

    opened by grzn 15
  • Please update the pypi package

    Please update the pypi package

    I spent most part of the last two days trying to figure out why the Publisher/Subscriber pattern wasn't working.

    After running pip install -I it worked on the first run.

    opened by medecau 14
  • problem with 3rd example on dotcloud.com

    problem with 3rd example on dotcloud.com

    this is the example where the server defines an exception class and the client calls the exception.

    running ubuntu, client blows up with this error:

    An error occurred: Traceback (most recent call last): File "/usr/local/lib/python2.7/dist-packages/zerorpc-0.4.4-py2.7.egg/zerorpc/core.py", line 148, in _async_task functor.pattern.process_call(self._context, bufchan, event, functor) File "/usr/local/lib/python2.7/dist-packages/zerorpc-0.4.4-py2.7.egg/zerorpc/patterns.py", line 30, in process_call result = functor(*req_event.args) File "/usr/local/lib/python2.7/dist-packages/zerorpc-0.4.4-py2.7.egg/zerorpc/decorators.py", line 44, in call return self._functor(_args, *_kargs) File "zerorpc_server3.py", line 5, in bad raise Exception(":P") Exception: :P

    the server reports the error below, but does not blow up:

    No handlers could be found for logger "zerorpc.core"

    opened by schaefer0 13
  • Cross-programming language doesn't quite work

    Cross-programming language doesn't quite work

    I've got backend written in Python (3.4) and frontend written in Node.js. But I've got problem with my python backend since it starts immediately throwing errors when Node.js client connects:

    >>> Try now: 'zerorpc --client --connect tcp://127.0.0.1:9998 get_all_cont_ips'
    Traceback (most recent call last):
      File "/home/mark/tmp/scratch-1462829713/virtualenv/lib/python3.5/site-packages/gevent/greenlet.py", line 534, in run
        result = self._run(*self.args, **self.kwargs)
      File "/home/mark/tmp/scratch-1462829713/virtualenv/lib/python3.5/site-packages/zerorpc/core.py", line 142, in _async_task
        channel = self._multiplexer.channel(initial_event)
      File "/home/mark/tmp/scratch-1462829713/virtualenv/lib/python3.5/site-packages/zerorpc/channel.py", line 103, in channel
        return Channel(self, from_event)
      File "/home/mark/tmp/scratch-1462829713/virtualenv/lib/python3.5/site-packages/zerorpc/channel.py", line 122, in __init__
        self._channel_id = from_event.header[b'message_id']
    KeyError: b'message_id'
    <Greenlet at 0x7f12b0894c28: <bound method ServerBase._async_task of <zerorpc.core.Server object at 0x7f12af1266a0>>(<zerorpc.events.Event object at 0x7f12acb9b750>)> failed with KeyError
    

    And Node.js client throws error after 10 seconds:

    { HeartbeatError: Lost remote after 10000ms
        at Error (native)
        at Object.createErrorResponse (/home/mark/tmp/scratch-1462829713/RedPowder/server-management/node_modules/zerorpc/lib/util.js:53:10)
        at ClientChannel.<anonymous> (/home/mark/tmp/scratch-1462829713/RedPowder/server-management/node_modules/zerorpc/lib/client.js:147:26)
        at emitOne (events.js:96:13)
        at ClientChannel.emit (events.js:188:7)
        at Timeout._repeat (/home/mark/tmp/scratch-1462829713/RedPowder/server-management/node_modules/zerorpc/lib/channel.js:198:18)
        at Timeout.wrapper [as _onTimeout] (timers.js:417:11)
        at tryOnTimeout (timers.js:224:11)
        at Timer.listOnTimeout (timers.js:198:5) name: 'HeartbeatError' } undefined false
    

    Is this because Node.js and Python zerorpc API got out-of-sync or they weren't meant to work together at all? Or just Python3.4 version of ZeroRPC is incompatible?

    opened by mikroskeem 12
  • Server response periodically blocks?

    Server response periodically blocks?

    Hello,

    I will provide a reproduction example, but first, I am aware that what I'm doing isn't normal. I believe technically, this should be able to work.

    It seems that sending return values is periodically blocking indefinitely. I'm not sure why this is occuring.

    If you run the below example and run

    for i in {1..100} ; do zerorpc --timeout 1 tcp://localhost:5559 lolita ; done
    

    You'll notice that ever 5th or so request results in a timeout. But from the debug output in the server, you can see that the rpc method is executed and only appears to block while sending the response to the broker.

    Is there a better way to do this?

    # main.py 
    # A lot of debugging junk in here
    import gevent
    from gevent import monkey
    
    monkey.patch_all()
    
    import gipc
    
    from zmq import green as zmq
    
    import zerorpc
    import logging
    import multiprocessing as mp
    
    from zerorpc.socket import SocketBase
    from zerorpc.core import ServerBase
    from .util import zhelpers as zhelpers
    
    class SrvBase(ServerBase, SocketBase):
        def __init__(self, methods=None, name=None, context=None, pool_size=1000, heartbeat=5):
            SocketBase.__init__(self, zmq.XREP, context)
            if methods is None:
                methods = self
    
            name = name or ServerBase._extract_name(methods)
            methods = ServerBase._filter_methods(SrvBase, self, methods)
            ServerBase.__init__(self, self._events, methods, name, context, pool_size, heartbeat)
    
            # print "DEBUG TEST"
            # print self.__dict__
    
        def close(self):
            ServerBase.close(self)
            SocketBase.close(self)
    
    class RPCWorker(SrvBase):
        def lolita(self):
            return 42
    
        def add(self, a, b):
            return a + b
    
    def initializer(url="tcp://127.0.0.1:5560"):
        def do_work():
            class MySrv(SrvBase):
                def lolita(self):
                    print "ME"
                    return 42
    
                def add(self, a, b):
                    return a + b
    
            srv = MySrv()
            print "BREAK"
            srv.connect(url)
            print "BREAK1"
            gevent.spawn(srv.run)
            print "BREAK2"
            while True:
                gevent.sleep(0.50)
    
        monkey.patch_all()
    
        THREADPOOL = gevent.get_hub().threadpool
        threads = []
        for i in range(5):
            t = THREADPOOL.spawn(do_work)
            threads.append( t )
    
        print threads
    
        while True:
            # print "TICK"
            gevent.sleep(0.50)
    
    class DataPool:
        def __init__(self):
            self.ctx = zmq.Context.instance()
            try:
                # Socket facing clients
                self.frontend = self.ctx.socket(zmq.XREP)
                self.frontend.bind("tcp://127.0.0.1:5559")
    
                # Socket facing services
                self.backend = self.ctx.socket(zmq.XREQ)
                self.backend.bind("tcp://127.0.0.1:5560")
    
                # Socket poller
                self.poller = zmq.Poller()
                self.poller.register(self.frontend, zmq.POLLIN)
                self.poller.register(self.backend, zmq.POLLIN)
    
                # Start pool
                # self.pool = mp.Pool(processes=4, initializer=initializer)
                procs = []
                for i in xrange(10):
                    p = gipc.start_process(initializer)
                    procs.append(p)
                # p = mp.Process(target=initializer)
                # p.start()
            except Exception, e:
                raise
    
        def run(self, *args, **kwargs):
            gevent.spawn(self.run_loop)
    
        def run_loop(self):
            try:
                while True:
                    # print "TICK"
                    socks = dict(self.poller.poll(100))
    
                    gevent.sleep(0)
                    if socks.get(self.frontend) == zmq.POLLIN:
                        message = self.frontend.recv(zmq.NOBLOCK)
                        more = self.frontend.getsockopt(zmq.RCVMORE)
                        if more:
                            print "Rtr<<",
                            gevent.spawn(zhelpers.dump_part, message)
                            self.backend.send(message, zmq.SNDMORE)
                            print "SENDMORE"
                            gevent.sleep(0)
                        else:
                            print "Rtr<.",
                            gevent.spawn(zhelpers.dump_part, message)
                            self.backend.send(message, zmq.NOBLOCK)
    
                    gevent.sleep(0)
                    if socks.get(self.backend) == zmq.POLLIN:
                        message = self.backend.recv(zmq.NOBLOCK)
                        more = self.backend.getsockopt(zmq.RCVMORE)
                        if more:
                            print "Rtr>>",
                            gevent.spawn(zhelpers.dump_part, message)
                            self.frontend.send(message, zmq.SNDMORE)
                            print "RECEIVEMORE"
                            gevent.sleep(0)
                        else:
                            print "Rtr>.",
                            gevent.spawn(zhelpers.dump_part, message)
                            self.frontend.send(message, zmq.NOBLOCK)
                    gevent.sleep(0)
            except Exception, e:
                print e
                print "bringing down zmq device"
            finally:
                pass
                self.frontend.close()
                self.backend.close()
                self.ctx.term()
    
    # util.zhelpers
    from random import randint
    
    import zmq
    import msgpack
    
    
    # Receives all message parts from socket, prints neatly
    def dump(zsocket):
        print "----------------------------------------"
        for part in zsocket.recv_multipart():
            dump_part(part)
    
    def dump_part(part):
        # print part
        try:
            # dec_part = format_part( part )
            # dec_part = msgpack.unpackb(part)
            unpacker = msgpack.Unpacker(encoding='utf-8')
            unpacker.feed(part)
            dec_part = unpacker.unpack()
        except Exception, e:
            print "Can't unpack %s" % e
            dec_part = format_part( part )
        finally:
            print "[%03d]" % len(part), dec_part
        # print "[%03d]" % len(part), format_part( part )
    
    def format_part(part):
        if all(31 < ord(c) < 128 for c in part):
            return "'" + part + "'"
        else:
            return "0x" + "".join("%x" % ord(c) for c in part)
    
    # Set simple random printable identity on socket
    def set_id(zsocket):
        identity = "%04x-%04x" % (randint(0, 0x10000), randint(0, 0x10000))
        zsocket.setsockopt(zmq.IDENTITY, identity)
    
    opened by lordnynex 11
  • Heartbeat trying to emit on None object

    Heartbeat trying to emit on None object

    This happens from time to time with 40+ clients that all have a lot of network and cpu load. I have no idea it this causes the request to fail, but I'm sure it crashes the current (heartbeat?) greenlet, which is never a good thing.

    Traceback (most recent call last):
      File "/madcrew/applications/software/virtualenvs/otis_v0_1_0-linux/lib/python2.7/site-packages/gevent/greenl
    et.py", line 328, in run
        result = self._run(*self.args, **self.kwargs)
      File "/madcrew/applications/software/virtualenvs/otis_v0_1_0-linux/lib/python2.7/site-packages/zerorpc/heart
    beat.py", line 79, in _heartbeat
        self._channel.emit('_zpc_hb', (0,))  # 0 -> compat with protocol v2
    AttributeError: 'NoneType' object has no attribute 'emit'
    <Greenlet at 0x70a7370: <bound method HeartBeatOnChannel._heartbeat of <zerorpc.heartbeat.HeartBeatOnChannel o
    bject at 0x88c4c90>>> failed with AttributeError
    

    We also get a lot of these, but I suspect we are to aggressive calling combined with a high network load, which makes it acceptable:

    /!\ gevent_zeromq BUG /!\ catching up after missing event (RECV) /!\
    
    opened by maxekman 11
  • TypeError: ord() expected string of length 1 on clear windows install

    TypeError: ord() expected string of length 1 on clear windows install

    I've reinstalled clean python (2.7.12) and installed zerorpc via pip Scripts/pip.exe install zerorpc

    Trying to run an example gives: Traceback (most recent call last): File "C:\Python27\lib\site-packages\zerorpc\channel.py", line 78, in _channel_dispatcher event = self._events.recv() File "C:\Python27\lib\site-packages\zerorpc\events.py", line 365, in recv event = Event.unpack(get_pyzmq_frame_buffer(blob)) File "C:\Python27\lib\site-packages\zerorpc\events.py", line 215, in unpack unpacked_msg = unpacker.unpack() File "C:\Python27\lib\site-packages\msgpack\fallback.py", line 570, in unpack ret = self._fb_unpack(EX_CONSTRUCT, write_bytes) File "C:\Python27\lib\site-packages\msgpack\fallback.py", line 498, in _fb_unpack typ, n, obj = self._read_header(execute, write_bytes) File "C:\Python27\lib\site-packages\msgpack\fallback.py", line 347, in _read_header b = ord(c) TypeError: ord() expected string of length 1, but memoryview found

    I've zerorpc version 0.6.0, msgpack version 0.4.8.

    opened by y666 10
  • Could there be a way for video streaming?

    Could there be a way for video streaming?

    Hi.

    I'm trying to implement Video Streaming using your code, but i have some trouble.

    I wish to change the "depth" variable for HelloData() class in the while loop, but if the code meets run() it seems it doesn't pass until the connection between server and the client are closed.

    Is there anyway ( such as loop ) to maintain the connection, but changing the variable of the class?

    Below are the codes.

    Thanks!

    while True:
            # Get capture
            capture = device.update()
    
            # Get the color depth image from the capture
            #ret, depth_image = capture.get_colored_depth_image()
            ret, depth_image = capture.get_depth_image()
            
            #if not ret:
            #        continue
            
            np.save("./16_depth_s",depth_image)
            
            #print(depth_image.dtype)
            s = zerorpc.Server(HelloData())
            s.bind("tcp://*:4242")
            s.run()
    
    
    
    
    class HelloData(object):
        def __init__(self):
            self.depth = np.load("/home/dbkim/kinect/16_depth_s.npy")
            zarr.save('test4.zarr', self.depth)
            self.rgb = cv2.imread("color_s.png")
    
    opened by DongBumKim 1
  • docs: Fix a few typos

    docs: Fix a few typos

    There are small typos in:

    • doc/protocol.md
    • zerorpc/core.py

    Fixes:

    • Should read transferred rather than transfered.
    • Should read occurred rather than occured.

    Semi-automated pull request generated by https://github.com/timgates42/meticulous/blob/master/docs/NOTE.md

    opened by timgates42 0
  • gevent_zmq: import enums from pyzmq >= 23.0.0

    gevent_zmq: import enums from pyzmq >= 23.0.0

    With pyzmq 23.0.0, constants were changed to enums and moved to the constants module. Attempt to import all globals from it into our zmq wrapper.

    Closes: #251 Signed-off-by: Cedric Hombourger [email protected]

    opened by chombourger 1
  • v0.6.3 is incompatible with pyzmq 23.0.0

    v0.6.3 is incompatible with pyzmq 23.0.0

    The pyzmq project has recently released 23.0.0

    One of the changes highlighted in the release notes is:

    all zmq constants are now available as Python enums (e.g. zmq.SocketType.PULL, zmq.SocketOption.IDENTITY), generated statically from zmq.h instead of at compile-time. This means that checks for the presence of a constant (hasattr(zmq, 'RADIO')) is not a valid check for the presence of a feature. This practice has never been robust, but it may have worked sometimes. Use direct checks via e.g. zmq.has() or zmq.zmq_version_info().

    I am getting errors like this one when running against that release

    AttributeError: module 'zerorpc.gevent_zmq' has no attribute 'PUSH'
    
    opened by chombourger 1
  • module 'collections' has no attribute 'Iterator'

    module 'collections' has no attribute 'Iterator'

    To reproduce:

    $ zerorpc --server --bind tcp://*:1234 time
    $ zerorpc --client --connect tcp://127.0.0.1:1234 strftime %Y/%m/%d
    

    Error at client side:

    connecting to "tcp://127.0.0.1:1234"
    Traceback (most recent call last):
      File "/sbin/zerorpc", line 33, in <module>
        sys.exit(load_entry_point('zerorpc==0.6.3', 'console_scripts', 'zerorpc')())
      File "/usr/lib/python3.10/site-packages/zerorpc/cli.py", line 310, in main
        return run_client(args)
      File "/usr/lib/python3.10/site-packages/zerorpc/cli.py", line 270, in run_client
        if not isinstance(results, collections.Iterator):
    AttributeError: module 'collections' has no attribute 'Iterator'
    
    opened by glyh 1
Owner
zerorpc
A set of RPC libraries, intuitive to use, decently fast, and cross-language.
zerorpc
Nuitka Organization 8k Jan 7, 2023
Scapy: the Python-based interactive packet manipulation program & library. Supports Python 2 & Python 3.

Scapy Scapy is a powerful Python-based interactive packet manipulation program and library. It is able to forge or decode packets of a wide number of

SecDev 8.3k Jan 8, 2023
Simple plotting for Python. Python wrapper for D3xter - render charts in the browser with simple Python syntax.

PyDexter Simple plotting for Python. Python wrapper for D3xter - render charts in the browser with simple Python syntax. Setup $ pip install PyDexter

D3xter 31 Mar 6, 2021
Implementation of hashids (http://hashids.org) in Python. Compatible with Python 2 and Python 3

hashids for Python 2.7 & 3 A python port of the JavaScript hashids implementation. It generates YouTube-like hashes from one or many numbers. Use hash

David Aurelio 1.4k Jan 2, 2023
Python library for serializing any arbitrary object graph into JSON. It can take almost any Python object and turn the object into JSON. Additionally, it can reconstitute the object back into Python.

jsonpickle jsonpickle is a library for the two-way conversion of complex Python objects and JSON. jsonpickle builds upon the existing JSON encoders, s

null 1.1k Jan 2, 2023
tinykernel - A minimal Python kernel so you can run Python in your Python

tinykernel - A minimal Python kernel so you can run Python in your Python

fast.ai 37 Dec 2, 2022
Python-experiments - A Repository which contains python scripts to automate things and make your life easier with python

Python Experiments A Repository which contains python scripts to automate things

Vivek Kumar Singh 11 Sep 25, 2022
pycallgraph is a Python module that creates call graphs for Python programs.

Project Abandoned Many apologies. I've stopped maintaining this project due to personal time constraints. Blog post with more information. I'm happy t

gak 1.7k Jan 1, 2023
Python Fire is a library for automatically generating command line interfaces (CLIs) from absolutely any Python object.

Python Fire Python Fire is a library for automatically generating command line interfaces (CLIs) from absolutely any Python object. Python Fire is a s

Google 23.6k Dec 31, 2022
MySQL database connector for Python (with Python 3 support)

mysqlclient This project is a fork of MySQLdb1. This project adds Python 3 support and fixed many bugs. PyPI: https://pypi.org/project/mysqlclient/ Gi

PyMySQL 2.2k Dec 25, 2022
㊙️ Create standard barcodes with Python. No external dependencies. 100% Organic Python.

python-barcode python-barcode provides a simple way to create barcodes in Python. There are no external dependencies when generating SVG files. Pillow

Hugo Barrera 419 Dec 26, 2022
Crab is a flexible, fast recommender engine for Python that integrates classic information filtering recommendation algorithms in the world of scientific Python packages (numpy, scipy, matplotlib).

Crab - A Recommendation Engine library for Python Crab is a flexible, fast recommender engine for Python that integrates classic information filtering r

python-recsys 1.2k Dec 21, 2022
xlwings is a BSD-licensed Python library that makes it easy to call Python from Excel and vice versa. It works with Microsoft Excel on Windows and macOS. Sign up for the newsletter or follow us on twitter via

xlwings - Make Excel fly with Python! xlwings CE xlwings CE is a BSD-licensed Python library that makes it easy to call Python from Excel and vice ver

xlwings 2.5k Jan 6, 2023
Official Python client for the MonkeyLearn API. Build and consume machine learning models for language processing from your Python apps.

MonkeyLearn API for Python Official Python client for the MonkeyLearn API. Build and run machine learning models for language processing from your Pyt

MonkeyLearn 157 Nov 22, 2022
PRAW, an acronym for "Python Reddit API Wrapper", is a python package that allows for simple access to Reddit's API.

PRAW: The Python Reddit API Wrapper PRAW, an acronym for "Python Reddit API Wrapper", is a Python package that allows for simple access to Reddit's AP

Python Reddit API Wrapper Development 3k Dec 29, 2022
RPyC (Remote Python Call) - A transparent and symmetric RPC library for python

RPyC (pronounced like are-pie-see), or Remote Python Call, is a transparent library for symmetrical remote procedure calls, clustering, and distribute

null 1.3k Jan 5, 2023