Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/350.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在树结构上递归调用任务_Python_Django_Asynchronous_Celery - Fatal编程技术网

Python 在树结构上递归调用任务

Python 在树结构上递归调用任务,python,django,asynchronous,celery,Python,Django,Asynchronous,Celery,如果这仅仅是由于我的误解,我道歉。我一直在四处搜索和阅读文档,但一直无法找到适合我的解决方案 我有一个树结构,每个节点可以有任意数量的子节点。对于每个节点,将实例化一个新的芹菜任务来创建它,然后它将查看所有子节点并实例化新任务来创建这些子节点。这样做的原因是为了更好地利用芹菜的多线程特性。递归地创建整个树的单个任务似乎只利用了单个线程 虽然我能够以这样的方式设置代码,但问题是,在创建整个结构之前,我在原始任务中有一些依赖项无法执行。代码如下所示: @app.task def initial_ta

如果这仅仅是由于我的误解,我道歉。我一直在四处搜索和阅读文档,但一直无法找到适合我的解决方案

我有一个树结构,每个节点可以有任意数量的子节点。对于每个节点,将实例化一个新的芹菜任务来创建它,然后它将查看所有子节点并实例化新任务来创建这些子节点。这样做的原因是为了更好地利用芹菜的多线程特性。递归地创建整个树的单个任务似乎只利用了单个线程

虽然我能够以这样的方式设置代码,但问题是,在创建整个结构之前,我在原始任务中有一些依赖项无法执行。代码如下所示:

@app.task
def initial_task(tree_data):
    jobs = []
    for node in tree_data:
        jobs.append(recursive_task.s(node))
    job = group(jobs)
    result = job.apply_async()

    # Block execution until group is finished
    while not result.ready():
        time.sleep(0.5)

    ... do dependent stuff ...

@app.task
def recursive_task(node, parent=None):
    # Create node object
    node_obj = Node(node.name, parent=parent)

    jobs = []
    for child in node.children:
        jobs.append(recursive_task.s(child, node_obj))
    job = group(jobs)
    result = job.apply_async()

    return node_obj
我遇到的问题是,所有孩子的子任务都不会阻碍第一组任务的完成,我不知道如何强制做到这一点。在这件事上的任何帮助都将不胜感激

因为在创建子节点时需要node_obj的ID,所以不能简单地递归树并链接任务

更新: 我对代码做了一些修改,试图改变结果。以下代码导致所有子节点(包括孙子、曾孙等)都是顶级节点的直接子节点:

@app.task
def initial_task(tree_data):
    def _recursive_link_task(task_set, children):
        for child in children:
            task_set.link(create_node.s(child))

            if child.children:
                _recursive_link_task(task_set, child.children)


    for node in tree_data:
        s = create_node.s(None, node)
        if node.children:
            _recursive_link_task(s, node.children)
        s.apply_async()

@app.task
def create_node(parent, node):
    node_obj = Node(node.name, parent=parent)
    return (node_obj,)
我原以为通过上面的代码片段我可能会有更多的财富,但由于它只是传递给所有后续任务的初始节点对象,因此我仍然没有进一步尝试生成此树结构。

用于执行依赖于一组任务结果的任务

由于我无法确切理解您需要如何调用递归任务,因此我实现了一个合并排序示例

注意这在芹菜3.2.0+上不起作用,因为在任务内调用
get
将导致异常

from celery import Celery, chord
app = Celery('tasks', backend='amqp', broker='amqp://')
app.conf.CELERY_RESULT_BACKEND = 'amqp'


def mergesort(list_obj):
    '''normal mergesort
    '''
    if len(list_obj) <= 1:
        return list_obj
    middle = len(list_obj) / 2
    left, right = list_obj[:middle], list_obj[middle:]
    return list(merge(list(mergesort(left)), list(mergesort(right))))

def merge(left, right):
    '''normal merge
    '''
    while 1:
        if left == []:
            for j in right:
                yield j
            break
        elif right == []:
            for j in left:
                yield j
            break
        elif left[0] < right[0]:
            yield left.pop(0)
        else:
            yield right.pop(0)

def merge2(left_r, right_r):
    '''celery merge
    '''
    left =left_r.get()
    right = right_r.get()
    while 1:
        if left == []:
            for j in right:
                yield j
            break
        elif right == []:
            for j in left:
                yield j
            break
        elif left[0] < right[0]:
            yield left.pop(0)
        else:
            yield right.pop(0)
@app.task
def merge_c(in_list):
    '''celery merge
    '''
    #unpack
    print '*'*21 + str( in_list)
    left, right = in_list
    return list(merge2(left, right))

@app.task
def same_object(l_obj):
    '''helper function to convert list to `result`
    '''
    return l_obj

@app.task
def mergesort_c(list_obj):
    '''celery mergesort
    '''
    if len(list_obj) <= 1:
        # make sure that you return a `result` object for merge
        return same_object.delay(list_obj)
    middle = len(list_obj) / 2
    left, right = list_obj[:middle], list_obj[middle:]
    # finish mergesort (left) and mergesort(right) and merge them
    res = chord([mergesort_c.s(left), mergesort_c.s(right)])(merge_c.s())
    return res

if __name__ == '__main__':
    l = [2,1, 3]
    #normal mergesort
    print mergesort(l) #[1, 2, 3, 3, 5]
    # with celery
    res = mergesort_c(l)
    print res.get()
从芹菜导入芹菜,chord
app=芹菜('tasks',backend='amqp',broker='amqp://'))
app.conf.芹菜\结果\后端='amqp'
def合并排序(列表对象):
“正常合并排序”
'''

如果len(列出对象)对此表示感谢。如果我有机会,我会看看我是否能将它应用到我正在编写的代码中。我曾经尝试过将任务链接起来——也许一个和弦可以提供更好的结果。祝你好运。同时,我将努力找到一个不会被新芹菜否定的答案:)