扩展 celery.schedules.schedule 对象未传递额外参数

Extended celery.schedules.schedule objects aren't passed extra arguments

The code is here.

我写了一个 celery.schedules.schedule 接口的扩展,但我不明白为什么它在我创建的额外值中没有任何设置的情况下被实例化。

当我在传递给 app.conf.CELERYBEAT_SCHEDULE 之前实例化它们时,它们是正确的。但是celery beat实例化的都是不正确的。

我在#celery IRC chan 中询问,我得到的唯一回复是关于懒惰模式,但那是针对 celery.beat.Scheduler,而不是 celery.schedules.schedule,所以如果它相关,我不明白如何.我是否也必须扩展它,以便它正确地实例化时间表?

我已经尝试深入研究 celery 代码 w/the 调试器以找出这些计划的实例化位置,但我找不到它。我可以看到他们从 Unpickler 回来时他们错了,但我找不到他们在哪里创建或在哪里腌制。

在 Python 调试器中花费了大量时间后,我将问题缩小到 celery.beat.PersistentScheduler.sync() and/or shelve.sync()(由前者)。

同步搁置时,值会丢失。我不知道为什么,但我很确定这是 Celery 或 Shelve 中的错误。

In any case, I wrote a workaround.

celery.schedules.schedule 有一个 __reduce__ 方法,它定义了如何使用 pickle 序列化和重建对象:

https://github.com/celery/celery/blob/master/celery/schedules.py#L150-L151

当 pickle 序列化对象时,它将调用:

fun, args = obj.__reduce__()

并且当它重建对象时它会做:

obj = fun(*args)

因此,如果您已将新状态添加到您的自定义计划子类中,并作为参数传递给 __init__,那么您将 还必须定义一个 __reduce__ 方法来接受这些 考虑新参数:

class myschedule(schedule):

    def __init__(self, run_every=None, relative=False, nowfun=None,
                 odds=None, max_run_every=None, **kwargs):
        super(myschedule, self).__init__(
            run_every, relative, nowfun, **kwargs)
        self.odds = odds
        self.max_run_every = max_run_every

    def __reduce__(self):
        return self.__class__, (
            self.run_every, self.relative, self.nowfun,
            self.odds, self.max_run_every)