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 useIOLoop.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
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 inw.run()
(self.loop.make_current()
.loop.start()
will callmake_current()
for you).