inlineCallbacks函数内的回调

3 投票
2 回答
1231 浏览
提问于 2025-04-16 19:13

假设我有一个这样的函数:

def display(this, that):
    print this, that

还有一个类:

class Runner(object):
    def __init__(self, callback):
        self.callback = callback
        self.loop = twisted.internet.task.LoopingCall(repeat)
        self.loop.start(0)

    @defer.inlineCallbacks
    def repeat(self):
        this = yield do_this()
        that = yield do_that()

        if this and that:
            # now I want to call the callback function
            yield self.callback(this, that) # makes sense?

runner = Runner(display)
reactor.run()

基本上,我想做的是创建一个 Runner 类,这个类会执行一些特定的任务,每当它得到一个结果时,就会调用给定的回调函数。与其创建一个新的函数来做某件特定的事情,我想创建一个通用的类,只做一件事情。例如:

class TwitterReader(object):
    def __init__(self, callback):
        ...
        ...

    @defer.inlineCallbacks
    def get_messages(self):
        ...
        ...
        yield callback(messages)

class MessageFilter(object):
    def __init__(self):
        self.bad_messages = open('bad_messages.txt', 'w')
        self.twitter = TwitterReader(self.message_received)

    def message_received(messages):
        for message in messages:
            for bad_word in BAD_WORDS:
                if bad_word in message:
                    self.bad_messages.write(message)
                    break

我刚接触 twisted,所以不太确定这样做是否正确。这样做可以吗?

谢谢

2 个回答

0

你只需要在调用 yield self.callback 的时候,如果它返回的是一个延迟对象(deferred),并且你想在退出 repeat 函数之前等到结果。那么在你的例子里,你的回调函数是一个普通的函数(实际上返回的是 None),所以使用 yield 并没有什么好处。不过,使用 yield 返回非延迟的值也是可以的,所以这样做并不会有坏处。根据inlineCallbacks 的文档

非延迟对象也可以被 yield,你的生成器会用同样的对象继续执行。这意味着 yield 的操作大致相当于 maybeDeferred。

如果你的回调函数 确实 返回了一个延迟对象(比如它也是一个带有 inlineCallbacks 装饰器的函数),那么使用 yield 会暂停 repeat 的执行,直到这个延迟对象完成。这在你的应用中可能是需要的,也可能不是。

2

你的问题是,repeat 里面的 callback 应该改成 self.callback

除此之外,你的例子应该可以照原样运行。

撰写回答