【问题标题】:Process messages from autobahn Subscriptions asynchronously, non-blocking异步、非阻塞地处理来自高速公路订阅的消息
【发布时间】:2017-10-17 16:49:35
【问题描述】:

我有一个在 docker 容器中运行的 python“设备”。它连接到 Crossbar 路由器,在订阅的频道上接收高速公路/WAMP 事件消息。

发布某个事件时,我的设备正在调用一个在几秒钟内完成的方法。 现在,我希望它在方法仍在运行时跳过或处理接收到的同一事件的任何消息。我尝试通过使用 Twisted 的 @inlinecallback 装饰器并在设备上设置“self.busy”标志来实现这一点。

但它并没有立即返回延迟,而是表现得像一个正常的阻塞方法,因此传入的消息被一个接一个地处理。

这是我的代码:

from autobahn.twisted.wamp import ApplicationSession
from twisted.internet.defer import inlineCallbacks

class Pixel(ApplicationSession):

@inlineCallbacks
def onJoin(self, details):
    yield self.subscribe(self.handler_no_access, 'com.event.no_access')

@inlineCallbacks
def handler_no_access(self, direction):
    entries = len(self.handlers['no_access'][direction])

    if entries == 0:
        self.handlers['no_access'][direction].append(direction)
        result = yield self._handler_no_access()
        return result

    else:
        yield print('handler_no_access: entries not 0: ', self.handlers['no_access'])

@inlineCallbacks
def _handler_no_access(self):
    for direction in self.handlers['no_access']:

        for message in self.handlers['no_access'][direction]:
            yield self._timed_switch(self.direction_leds[direction], 'red', 0.2, 5)
            self.handlers['no_access'][direction] = []

顺便说一句,我已经用 self.handler 字典走了一条老路。

编辑

拦截方式为:

yield self._timed_switch(self.direction_leds[direction], 'red', 0.2, 5)

它在 RaspberryPi 的 GPIO 上控制 Neopixel,让它闪烁 1 秒。对该方法的任何进一步调用

def handler_no_access(self, direction)

当 _timed_switch 没有完成时,应该被跳过,所以它们不会叠加。

解决方案

@inlineCallbacks
def handler_no_access(self, direction):
    direction = str(direction)

    if self.busy[direction] is False:

        self.busy[direction] = True

        # non-blocking now
        yield deferToThread(self._handler_no_access, direction)

    else:
        yield print('handler_no_access: direction {} busy '.format(direction))

def _handler_no_access(self, direction):

    # this takes 1s to execute
    self._timed_switch(self.direction_leds[direction], 'red', 0.2, 5)

    self.busy[direction] = False

【问题讨论】:

    标签: python docker twisted autobahn


    【解决方案1】:

    inlineCallbacks 不会将阻塞代码变成非阻塞代码。它只是使用 Deferreds 的替代 API。延迟只是管理回调的一种方式。

    您需要以其他方式将阻塞代码重写为非阻塞。你实际上并没有说你的代码的哪一部分被阻塞了,也没有说它阻塞了什么,所以很难建议你如何做到这一点。将阻塞代码变为非阻塞的仅有的两个通用工具是线程和进程。因此,您可以在单独的线程或进程中运行该函数。该函数可能会或可能不会在这样的执行上下文中工作(同样,如果不知道它究竟做了什么,就无法知道)。

    【讨论】:

    • 好吧,谢谢提醒,显然我对 Twisted 中的延迟机制有错误的理解。
    • link 我现在正在尝试使用 deferToThread(f) 并会报告,这是否解决了我的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-20
    • 1970-01-01
    • 2018-04-06
    • 2015-09-01
    • 1970-01-01
    • 2020-10-28
    • 1970-01-01
    相关资源
    最近更新 更多