Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/351.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_Celery - Fatal编程技术网

Python 如何用芹菜链等待任务完成?

Python 如何用芹菜链等待任务完成?,python,celery,Python,Celery,我试图在这里创建一个芹菜连锁店: chain(getAllProducts.s(shopname, hdrs), editOgTags.s(title, description, whichImage, readableShopname, currentThemeId), notifyBulkEditFinish.si(email, name, readableShopname, totalProducts), updateBulkEditTask.si(taskID))

我试图在这里创建一个芹菜连锁店:

chain(getAllProducts.s(shopname, hdrs),
    editOgTags.s(title, description, whichImage, readableShopname, currentThemeId),
    notifyBulkEditFinish.si(email, name, readableShopname, totalProducts),
    updateBulkEditTask.si(taskID))()
在editOgTags中,有3个子任务:

@shared_task(ignore_result=True)
def editOgTags(products, title, description, whichImage, readableShopname, currentThemeId):
    for product in products:
        editOgTitle.delay(product, title, readableShopname)
        editOgDescription.delay(product, description, readableShopname)
        editOgImage.delay(product, int(whichImage), currentThemeId)
在每个editOgXXX函数中,都有一个要使用速率限制调用的函数:

@shared_task(rate_limit='1/s')
def updateMetafield(index, loop_var, target_id, type_value):
    resource = type_value + 's'
    # print(f"loop_var key = {loop_var[index]['key']}")
    if type_value == 'product' or type_value == 'collection' or type_value == 'article' or type_value == 'page':
        meta = shopify.Metafield.find(resource=resource, resource_id=target_id, namespace='global', key=loop_var[index]['key'])
        checkAndWaitShopifyAPICallLimit()
    else:
        print("Not available metafield type! Cannot update.")
        return

    if meta:
        # meta[0].destroy()
        meta[0].value = loop_var[index]['value']
        meta[0].save()
    else:
        metafield = shopify.Metafield.create({
            'value_type': 'string',
            'namespace': 'global',
            'value': loop_var[index]['value'],
            'value-type': 'string',
            'key': loop_var[index]['key'],
            'resource': resource,
            'resource_id': target_id,
            })
        metafield.save()
在漏桶算法下,它一次提供40个api调用,2个reqs/s补充。因为shopify功能的速率限制为2次请求/秒。我将速率限制设置为1/s。当它用完api配额时,我将调用time.sleep(20)以等待CheckAndWaitShopIficationApicallLimit()中的补充

问题是在所有任务完成之前调用电子邮件通知功能(notifyBulkEditFinish)。如何确保在所有任务完成后调用电子邮件功能


我怀疑sleep函数会使任务落后于队列中的email函数。

要扩展@bruno的注释:使用
chord
并修改
editOgTags
函数来创建与通知相呼应的组:

from celery import chord

@shared_task(ignore_result=True)
def editOgTags(products, title, description, whichImage, readableShopname, currentThemeId, name, email, totalProducts):
    tasks = []
    for product in products:
        tasks.append(editOgTitle.si(product, title, readableShopname))
        tasks.append(editOgDescription.si(product, description, readableShopname))
        tasks.append(editOgImage.si(product, int(whichImage), currentThemeId))
    # kick off the chord, notifyBulk... will be called after all of these 
    # edit... tasks complete.
    chord(tasks)(notifyBulkEditFinish.si(email, name, readableShopname, totalProducts))

要扩展@bruno的注释:使用
chord
并修改
editOgTags
函数来创建一个与通知相呼应的组:

from celery import chord

@shared_task(ignore_result=True)
def editOgTags(products, title, description, whichImage, readableShopname, currentThemeId, name, email, totalProducts):
    tasks = []
    for product in products:
        tasks.append(editOgTitle.si(product, title, readableShopname))
        tasks.append(editOgDescription.si(product, description, readableShopname))
        tasks.append(editOgImage.si(product, int(whichImage), currentThemeId))
    # kick off the chord, notifyBulk... will be called after all of these 
    # edit... tasks complete.
    chord(tasks)(notifyBulkEditFinish.si(email, name, readableShopname, totalProducts))

你的问题在于“所有任务完成后”的定义

editOgTags
启动
len(产品)*3个子任务-显然每个子任务都会启动另一个异步子任务。如果您想在发送电子邮件之前等待所有这些任务执行完毕,则需要一些同步机制。芹菜的内置解决方案是
chord
对象。ATM,您的代码等待
editOgTags
完成,但此任务所做的唯一事情是启动其他子任务-然后返回,不管这些子任务本身是否完成


和弦就像一个组,但有回调。chain原语允许我们将签名链接在一起,这样一个签名被一个接一个地调用,基本上形成了回调链。将链更改为和弦有什么区别

请注意,我并不是说您必须用
和弦
替换整个
。提示:链、组和和弦是要执行的任务,因此您可以通过组合任务、链、组和和弦来创建复杂的工作流


如上所述,区别在于,
chord
将等待其头中的所有任务完成后再执行回调。这允许N个异步任务并行执行,但在运行回调之前仍要等待所有任务完成。当然,这需要对代码进行一些思考和可能的重新组织(因此,如果需要的话,可以考虑子任务),但这确实回答了您的问题:“如何确保在所有任务完成后调用电子邮件功能?”

您的问题在于“所有任务完成后”的定义

editOgTags
启动
len(产品)*3个子任务-显然每个子任务都会启动另一个异步子任务。如果您想在发送电子邮件之前等待所有这些任务执行完毕,则需要一些同步机制。芹菜的内置解决方案是
chord
对象。ATM,您的代码等待
editOgTags
完成,但此任务所做的唯一事情是启动其他子任务-然后返回,不管这些子任务本身是否完成


和弦就像一个组,但有回调。chain原语允许我们将签名链接在一起,这样一个签名被一个接一个地调用,基本上形成了回调链。将链更改为和弦有什么区别

请注意,我并不是说您必须用
和弦
替换整个
。提示:链、组和和弦是要执行的任务,因此您可以通过组合任务、链、组和和弦来创建复杂的工作流


如上所述,区别在于,
chord
将等待其头中的所有任务完成后再执行回调。这允许N个异步任务并行执行,但在运行回调之前仍要等待所有任务完成。这当然需要对代码进行一些思考和可能的重新组织(因此,如果需要的话,子任务会被考虑在内),但这确实回答了您的问题:“如何确保在所有任务完成后调用电子邮件功能?”

和弦就像一个组,但带有回调。chain原语允许我们将签名链接在一起,这样一个签名被一个接一个地调用,基本上形成了回调链。将链更改为chord有什么区别?chord就像一个组,但具有回调。chain原语允许我们将签名链接在一起,这样一个签名被一个接一个地调用,基本上形成了回调链。将链更改为chord有什么区别?请注意芹菜文档中的一个非常重要的注释:>chord中使用的任务不能忽略其结果。在实践中,这意味着您必须启用result_后端才能使用和弦。此外,如果在配置中将task_ignore_result设置为True,请确保将在chord中使用的各个任务定义为ignore_result=False。这适用于任务子类和修饰任务。不要在任务中使用
.get()
-请注意芹菜文档中的一个非常重要的注意事项:>和弦中使用的任务不能忽略其结果。在实践中,这意味着您必须启用result_后端才能使用和弦。此外,如果在配置中将task_ignore_result设置为True,请确保将在chord中使用的各个任务定义为ignore_result=False。这适用于任务子类和修饰任务。不要在任务中使用
.get()
,谢谢您的回答!“我能理解我的方法做错了什么。”本尼坎对此感到高兴