Python - 将修改后的回调传递给调度程序

时间:2015-01-17 05:36:18

标签: python-2.7 callback scrapy

Scrapy应用程序,但问题实际上是关于Python语言 - 专家可以在不知道框架的情况下立即回答这个问题。

我有一个名为CrawlWorker的课程,知道如何与所谓的“蜘蛛”交谈 - 安排他们的爬行,并管理他们的生命周期。

TwistedRabbitClient有一个CrawlWorker。客户端只知道如何与队列通信并将消息传递给工作人员 - 它通过使用下面的工作方法connect_to_scrape异步地从工作人员完成工作,以连接到正在运行的蜘蛛发出的信号: / p>

def connect_to_scrape(self, callback):
        self._connect_to_signal(callback, signals.item_scraped)

def _connect_to_signal(self, callback, signal):
    if signal is signals.item_scraped:
        def _callback(item, response, sender, signal, spider):
            scrape_config = response.meta['scrape_config']
            delivery_tag = scrape_config.delivery_tag

            callback(item.to_dict(), delivery_tag)
    else:
        _callback = callback

    dispatcher.connect(_callback, signal=signal)

因此,工作人员为Rabbit客户端提供了一层“工作反序列化”,他不了解蜘蛛,响应,发件人,信号,项目(任何与工作本身有关的内容) - 仅{{1}这些将作为JSON发布,并带有传递标签。

所以下面的回调没有正确注册(也没有错误):

dict

但是如果我删除def publish(self, item, delivery_tag): self.log('item_scraped={0} {1}'.format(item, delivery_tag)) publish_message = json.dumps(item) self._channel.basic_publish(exchange=self.publish_exchange, routing_key=self.publish_key, body=publish_message) self._channel.basic_ack(delivery_tag=delivery_tag) 中的if分支并直接连接回调(并修改_connect_to_signal以吸收所有不必要的参数),它就可以工作。

任何人都有任何想法?

1 个答案:

答案 0 :(得分:0)

所以,我通过在更一般的背景下重新陈述它来弄清楚为什么这不起作用:

import functools

from scrapy.signalmanager import SignalManager


SIGNAL = object()


class Sender(object):

    def __init__(self):
        self.signals = SignalManager(self)

    def wrap_receive(self, receive):
        @functools.wraps(receive)
        def wrapped_receive(message, data):
            message = message.replace('World', 'Victor')
            value = data['key']

            receive(message, value)

        return wrapped_receive

    def bind(self, receive):
        _receive = self.wrap_receive(receive)

        self.signals.connect(_receive, signal=SIGNAL,
                             sender=self, weak=False)

    def send(self):
        message = 'Hello, World!'
        data = {'key': 'value'}

        self.signals.send_catch_log(SIGNAL, message=message, data=data)


class Receiver(object):

    def __init__(self, sender):
        self.sender = sender
        self.sender.bind(self.receive)

    def receive(self, message, value):
        """Receive data from a Sender."""
        print 'Receiver received: {0} {1}.'.format(message, value)


if __name__ == '__main__':
    sender = Sender()
    receiver = Receiver(sender)

    sender.send()

当且仅当weak=False时才有效。

基本问题是当连接信号时,需要指定weak=False。希望比我更聪明的人可以解释为什么需要它。