【问题标题】:Celery tasks with unpickable arguments带有不可挑选参数的芹菜任务
【发布时间】:2013-11-06 17:14:47
【问题描述】:

我正在尝试实现一个消息队列系统以将操作推送到 AdWords API。

 class Call(object):
    @celery.task(filter=task_method)
    def MUTATE(self, operations):
        assert hasattr(self, '__throwaway_service')
        with self.__throwaway_service as sm:
            response = sm.mutate(operations)
        return response

由于我不能将服务实例用作参数(服务具有向 API 发送“get”或“mutate”请求的方法),我将其设置为外部属性,并在该特定服务的所有操作都完成时将其删除发送到 MQ。

'operations' 是包含字符串或 unicode 键和值的字典列表。

我还是得到了

PicklingError: Can't pickle <type 'instancemethod'>: attribute lookup __builtin__.instancemethod failed

我收到这个错误是因为 celery 任务完全使用了实例方法吗?实现这一点的最佳和 Pythonic 方式是什么?

【问题讨论】:

  • 我认为问题在于您的任务方法在一个类中,您可以尝试将您的“MUTATE”方法转换为一个普通的python函数并以这种方式测试它是否有效?跨度>
  • 好吧,问题出在服务实例上。我需要那个,因为它是在我推动操作的那个服务上。因此,如果我将方法作为函数,则 service 必须是一个参数,它不能,因为它不可选择。不幸的是,班级没有任何变化。我只是卡住了

标签: python celery message-queue mq google-ads-api


【解决方案1】:

要运行此MUTATE 任务,必须将Call 的实例传递给队列。我想你的电话,包含像__throwaway_service 这样的花哨的方法几乎是不可挑选的。所以你必须重新设计你的任务,在一个任务中重构self对象,然后应用原始的MUTATE

此外,您可能会发现 this reciepe 有助于找出究竟哪些对象不能被腌制。

更新

这种模式是否适用:

@celery.task
def mutate(service_settings, operations):
    service = Service(**service_settings)
    return service.mutate(operations)

【讨论】:

  • 我卡住了。您将如何重新设计此任务?我需要一个服务实例,我认为它是不可选择的部分,以及推送到该服务的操作。我真的想不出没有将服务作为实例属性或任务参数的另一种方式
  • 如何实例化这个实例?它只是带有一些身份验证参数的 api 包装器吗?您能否提供有关您的类/实例的更多详细信息。
  • 带有 MUTATE 的类是父类,没有 init。它从许多子类中收集操作(和相关服务)。收集完所有操作后,我想为每对服务操作调用 MUTATE 方法,并将其发送到队列。我应该把 MUTATE 方法放在一个孤立的类实例中吗?
  • 查看答案的更新。我不确定我是否理解你,你最好添加一些代码示例。
  • 是的,我需要在层次结构中更改相当多的代码,但基本上我在运行时获取服务实例太早了。现在,我传递参数来获取服务,而不是服务实例,然后调用者在其方法之一中实例化服务。
【解决方案2】:

操作中可能有一个对象。在将对象传递给 celery 任务之前,您需要将对象处理为字典或其他本机类型。

【讨论】:

    猜你喜欢
    • 2014-07-17
    • 2013-05-13
    • 1970-01-01
    • 2019-02-26
    • 2018-05-11
    • 2018-05-17
    • 1970-01-01
    • 2014-12-04
    • 2021-04-25
    相关资源
    最近更新 更多