Search code examples
pythonpython-2.7zeromqpython-multithreadingzerorpc

How do I handle multiple requests to python program using zeromq and threading or async?


I have a little program, which does some calculations in background, when I call it through zerorpc module in python 2.7.

Here is my code:

is_busy = False

class Server(object):
   def calculateSomeStuff(self):
       global is_busy

        if (is_busy):
            return 'I am busy!'

        is_busy = True

        # calculate some stuff

        is_busy = False
        print 'Done!'
        return 

    def getIsBusy(self):
        return is_busy

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

What should I change to make this program returning is_busy when I call .getIsBusy() method, after .calculateSomeStuff() has started doing it's job?

As I know, there is no way to make it asynchronous in python 2.


Solution

  • You need multi-threading for real concurrency and exploit more than one CPU core if this is what you are after. See the Python threading module, GIL-lock details & possible workarounds and literature.

    If you want a cooperative solution, read on.

    zerorpc uses gevent for asynchronous input/output. With gevent you write coroutines (also called greenlet or userland threads) which are all running cooperatively on a single thread. The thread in which the gevent input output loop is running. The gevent ioloop takes care of resuming coroutines waiting for some I/O event.

    The key here is the word cooperative. Compare that to threads running on a single CPU/core machine. Effectively there is nothing concurrent,
    but the operating system will preempt ( verb: take action in order to prevent (an anticipated event) from happening ) a running thread to execute the next on and so on so that every threads gets a fair chance of moving forward.

    This happens fast enough so that it feels like all threads are running at the same time.

    If you write your code cooperatively with the gevent input/output loop, you can achieve the same effect by being careful of calling gevent.sleep(0) often enough to give a chance for the gevent ioloop to run other coroutines.

    It's literally cooperative multithrading. I've heard it was like that in Windows 2 or something.

    So, in your example, in the heavy computation part, you likely have some loop going on. Make sure to call gevent.sleep(0) a couple times per second and you will have the illusion of multi-threading.

    I hope my answer wasn't too confusing.