Thread local pyzmq ioloop

444 views Asked by At

I was wondering if there is a way to have a thread local ioloop in pyzmq. The comment in the code says (https://github.com/zeromq/pyzmq/blob/master/zmq/eventloop/minitornado/ioloop.py line 172):

In general you should use IOLoop.current as the default when constructing an asynchronous object, and use IOLoop.instance when you mean to communicate to the main thread from a different one.

According to this I assume that using .current I should be able to create thread local ioloop which I can start/stop independently of the main thread ioloop.

Strangely, this is not the behavior that I observe (I use .current in the local thread, but doing .stop on this loop also stop main threads loop). Moreover, this simple test code:

import threading
from zmq.eventloop import ioloop

loop = ioloop.IOLoop.current()
print 'main id(loop):', id(loop)

class w(threading.Thread):
    def __init__(self, loop=None):
        super(w, self).__init__()

        self.loop = loop or ioloop.IOLoop.current()

        print 'w.__init__ id(loop):', id(self.loop)

    def run(self):
        print 'w.__run__ id(loop):', id(self.loop)
        print 'current:', id(ioloop.IOLoop.current())


w(loop).start()

prints the same ids for both loops:

main id(loop): 33576144
w.__init__ id(loop): 33576144
w.__run__ id(loop): 33576144
current: 33576144

I would be glad to understand what do I miss.

Alex

1

There are 1 answers

2
Ben Darnell On BEST ANSWER

IOLoop.current() has some quirks for historical reasons. It will refer to the thread-local event loop if one exists, but it will not create one, instead falling back to the singleton (main-thread) loop.

The solution is to create a new loop in w.__init__() (self.loop = ioloop.IOLoop()) and make it current in w.run() (self.loop.make_current(). loop.start() will call make_current() for you).