我想在后台线程中创建一个PyZMQ eventloop,并让它与独立的Python脚本和IPython脚本一起正常工作。 (IPython使用位于主线程中的PyZMQ eventloops,因此这会导致我出现问题以及为什么我要在后台线程中启动私有ioloop。)
我希望在线程A中运行代码,同时让PyZMQ eventloop句柄从线程B中的套接字接收数据。在线程A中有时候我需要等待线程B中的事件集。
我怎样才能让它发挥作用?如果我在IPython中尝试,似乎有些问题:
from zmq.eventloop import ioloop
import threading
class IOBackgroundLoop(object):
def __init__(self):
self._loop = None
self._thread = threading.Thread(target=self.run)
self._thread.daemon = True
self._started = threading.Event()
@property
def loop(self):
return self._loop
def run(self):
self._loop = ioloop.IOLoop()
self._loop.initialize()
self._loop.make_current()
self._started.set()
self._loop.start()
def start(self):
self._thread.start()
self._started.wait()
bkloop = IOBackgroundLoop()
bkloop.start()
for loop in [bkloop.loop, ioloop.IOLoop.instance()]:
print "%s running: %s" % (loop, loop._running)
这打印出两个独立的IOLoop实例,但如果我去使用它,它似乎不起作用。我想不出一个小例子程序来证明这一点;我尝试过使用超时功能:
import time
def print_timestamp(key):
print "%s: %s" % (time.time(), key)
for loop in [bkloop.loop, ioloop.IOLoop.instance()]:
loop.add_timeout(bkloop.loop.time() + 1.0, lambda: print_timestamp("hi from %s" % loop))
print_timestamp("here")
time.sleep(2.0)
print_timestamp("there")
我得到了这个结果(没有“嗨”:
1412889057.68: here
1412889059.68: there
1412889059.68: here
1412889061.68: there
然后当我点击另一个班次+ Enter时,我得到了
1412889061.68: hi from <zmq.eventloop.ioloop.ZMQIOLoop object at 0x000000000467E4E0>
这是主线程中的IOLoop对象,但我的私有实例IOLoop从不打印hi。
我可能做错了什么?
答案 0 :(得分:1)
唉,我刚才在龙卷风文档中注意到了这一点:
请注意,从其他线程调用
add_timeout
是不安全的。 相反,您必须使用add_callback
将控制转移到IOLoop
的主题,然后从那里调用add_timeout
。
似乎zmq.eventloop.zmqstream
需要在与ioloop相同的线程中设置才能正常工作。