Python龙卷风 - 如何在不停止循环的情况下创建阻塞调用?

时间:2014-01-09 12:59:38

标签: python tornado pyzmq

我正在使用ZMQ流,它们基于他们自己实现的龙卷风的IOLoop。我遇到了一个问题,我希望有同步行为,但IOLoop迫使我进入异步执行。具体如下:

我有一个专门负责相机设置的课程(相机处于不同的过程中):

class HamSettingsManager(object):
    ''' 
        This class makes sure the camera is set to the requested settings.
    '''
    def __init__(self, blabla, loop=None):
        self._msg = messaging.CamSettings(blabla)

        self._loop = loop or zmq.eventloop.ioloop.IOLoop()
        self._sub = messaging.StreamFactory.sub_stream(
            messaging.channel_map.DI().settings,
            loop=self._loop,
            on_recv=self._on_settings)

        self._pub = messaging.StreamFactory.pub_stream(
            messaging.channel_map.DI().update_settings,
            loop=self._loop)

    @tornado.gen.coroutine
    def set_settings(self):
        self._pub.send(self._msg.SerializeToString())
        self._new_settings = True
        self._changed = None
        while self._new_settings:
            log.debug("Waiting for camera settings to take effect.")
            yield tornado.gen.Task(self._loop.add_timeout, time.time() + 0.05)

    def _on_settings(self, data):
        msg = messaging.HamSettings()
        msg.ParseFromString(data[-1])

        if msg == self._msg:
            self._new_settings = False
        else:
            if not self._new_settings:
                log.warning("Someone has changed the camera settings underneath the aligner.")
                self._changed = time.time()

            log.debug("Settings not as expected, resending")
            log.debug("Current settings: \n%s" % msg)
            log.debug("Expected settings: \n%s" % self._msg)
            self._pub.send(self._msg.SerializeToString())

我期望发生的是set_settings只会在设置生效后才会返回,但实际发生的是执行只是继续,就像我生成一个线程一样。在IOLoop等待的正确方法是什么?

1 个答案:

答案 0 :(得分:2)

如果不停止事件循环,则无法创建阻止调用;这就是“阻塞”的含义。作为协程,set_settings立即返回Future;调用者负责等待Future被解决。通常,这意味着调用它的任何东西也必须是协程(或其他异步)并使用yield mgr.set_settings()而不是简单的调用。