Сельдерей: Как '|' оператор работает при цепочке нескольких задач?

Я знаю, что | — это побитовый оператор «ИЛИ», но мне интересно, как он работает в случае с сельдереем при объединении нескольких задач.

(first_task.s(url) | second_tasks.s()).apply_async()

Я знаю, что вторая задача будет принимать результат первой функции в качестве аргументов, но как это возможно? Где '|' перегрузка исходного кода dj-celery?

@task
def second_task(results):
   do_something(results)

Может кто-нибудь, пожалуйста, дать некоторые идеи?


person Humble Learner    schedule 14.07.2016    source источник


Ответы (2)


Как упоминалось выше, Celery переопределяет оператор __or__, в частности, следующим образом:

def __or__(self, other):
    if isinstance(other, group):
        other = maybe_unroll_group(other)
    if not isinstance(self, chain) and isinstance(other, chain):
        return chain((self, ) + other.tasks, app=self._app)
    elif isinstance(other, chain):
        return chain(*self.tasks + other.tasks, app=self._app)
    elif isinstance(other, Signature):
        if isinstance(self, chain):
            return chain(*self.tasks + (other, ), app=self._app)
        return chain(self, other, app=self._app)
    return NotImplemented

Полная реализация находится здесь: https://github.com/celery/celery/blob/master/celery/canvas.py#L324

person Elliot    schedule 14.07.2016

Вероятно, они используют перегрузку операторов как __or__(self, other): http://www.rafekettler.com/magicmethods.html

Я не знаю деталей реализации Celery, но просто чтобы дать вам представление:

class Task(object):
    def __init__(self, name):
        self.name = name
        self.chain = [self]

    def __or__(self, other):
        self.chain.append(other)
        return self

    def __repr__(self):
        return self.name

    def apply_async(self):
        for c in self.chain:
            print "applying", c


(Task('A') | Task('B') | Task('C')).apply_async()

Выход:

applying A
applying B
applying C
person synthomat    schedule 14.07.2016