如何序列化二进制文件以与芹菜任务一起使用



我最近在我的一个应用程序中集成了芹菜(更具体地说是django-芹菜)。我在应用程序中有一个模型如下:

class UserUploadedFile(models.Model)
    original_file = models.FileField(upload_to='/uploads/')    
    txt = models.FileField(upload_to='/uploads/')
    pdf = models.FileField(upload_to='/uploads/')
    doc = models.FileField(upload_to='/uploads/')
    
    def convert_to_others(self):
        # Code to convert the original file to other formats

现在,一旦用户上传文件,我想将原始文件转换为txt, pdf和doc格式。调用convert_to_others方法是一个昂贵的过程,所以我计划使用芹菜异步地做它。所以我写了一个简单的芹菜任务如下:

@celery.task(default_retry_delay=bdev.settings.TASK_RETRY_DELAY)
def convert_ufile(file, request):
    """ 
    This task method would call a UserUploadedFile object's convert_to_others
    method to do the file conversions.
    The best way to call this task would be doing it asynchronously
    using apply_async method.
    """
    try:
        file.convert_to_others()
    except Exception, err:
        # If the task fails log the exception and retry in 30 secs
        log.LoggingMiddleware.log_exception(request, err)
        convert_ufile.retry(exc=err)
    return True

,然后按如下方式调用任务:

ufile = get_object_or_404(models.UserUploadedFiles, pk=id)
tasks.convert_ufile.apply_async(args=[ufile, request])

现在,当apply_async方法被调用时,它会引发以下异常:

PicklingError: Can't pickle <type 'cStringIO.StringO'>: attribute lookup cStringIO.StringO failed

我认为这是因为芹菜(默认情况下)使用pickle库来序列化数据,而pickle无法序列化二进制文件。

问题

是否有其他序列化器可以自己序列化二进制文件?如果没有,我如何使用默认的pickle序列化器序列化二进制文件?

芹菜尝试pickle不支持pickle的数据是正确的。即使您能找到一种方法来序列化您想要发送给芹菜任务的数据,我也不会这样做。

发送尽可能少的数据到芹菜任务总是一个好主意,所以在你的情况下,我只传递一个UserUploadedFile实例的id。有了这个,您可以在芹菜任务中通过id获取对象并执行convert_to_others()

还请注意,对象可以在任务执行之前改变其状态(甚至可以删除)。因此,在芹菜任务中获取对象要比发送其完整副本安全得多。

总而言之,只发送一个实例id并在task中重新获取它会给你一些东西:

  • 你发送更少的数据到你的队列
  • 您不必处理数据不一致问题。
  • 这在你的情况下实际上是可能的。:)

唯一的"缺点"是,你需要执行一个额外的,廉价的SELECT查询来重新获取你的数据,这在总体上看起来像一个很好的交易,当与上述问题相比,不是吗?

相关内容

  • 没有找到相关文章

最新更新