我想在后台线程中创建一个PyZMQ事件循环,并使其与独立的Python脚本和IPython脚本均能正常工作。 (IPython使用位于主线程中的PyZMQ事件循环,因此这给我带来了问题,以及为什么我要在后台线程中启动私有ioloop。)

我要在线程A中运行代码,同时让PyZMQ事件循环句柄从线程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


然后当我再按一次Shift + Enter时,我得到

1412889061.68: hi from <zmq.eventloop.ioloop.ZMQIOLoop object at 0x000000000467E4E0>


这是主线程中的IOLoop对象,但是我的私有实例IOLoop从不打印嗨。

我可能做错了什么?

最佳答案

啊,我只是在龙卷风文档中注意到了这一点:


  请注意,从其他线程调用add_timeout是不安全的。
          相反,您必须使用add_callback将控制权转移到
          IOLoop的线程,然后从那里调用add_timeout


似乎还需要在与ioloop相同的线程中设置zmq.eventloop.zmqstream才能使其正常工作。

关于python - 运行第二个zmq.eventloop.ioloop,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26288066/

10-09 17:18