【问题标题】:How can I pass TemporaryUploadedFile to celery task?如何将 TemporaryUploadedFile 传递给 celery 任务?
【发布时间】:2016-02-28 10:53:00
【问题描述】:

我有一个代码:

def post(self, request, *args, **kwargs):
    file = request.FILES["import_file"]
    # create a tast with celery and save ID of the task
    task_id = importing.delay(file).id
    return Response({"task_id": task_id}, content_type="application/json")

当 type(file) 为 TemporaryUploadedFile 时出现错误,因为文件无法写入 redis。

我可以取这个临时文件的名字并将这个名字保存到 Redis 中。然后 celery worker 可以从 redis 中获取这个名字并读取文件。但我不确定:是否可以在 celery worker 从 redis 获得名称之前删除文件?

【问题讨论】:

  • 文件是临时的,这意味着它可以在芹菜工人打开它之前被删除。

标签: python django redis celery temporary-files


【解决方案1】:

TemporaryUploadedFile 会在request_finished 信号被触发后立即关闭并移除。当您的 Celery 工作人员访问该文件时,该文件很可能不再存在。

您应该将文件复制到一个永久位置,并在完成后让 Celery 清理该文件。

【讨论】:

  • 我已经实现了,我正在将上传的文件复制到新路径并将路径传递给 celery 作业,但 celery 说找不到文件,知道吗?
【解决方案2】:
    def close(self):
        try:
            return self.file.close()
        except OSError as e:
            if e.errno != errno.ENOENT:
                # Means the file was moved or deleted before the tempfile
                # could unlink it.  Still sets self.file.close_called and
                # calls self.file.file.close() before the exception
                raise

根据 TemporaryUploadedFile 的close 方法的源代码,如果临时文件被移动,它不会被关闭,所以你可以移动它并将它的新路径传递给 celery 任务,然后在 celery 任务完成时自行删除它。 这样,您将节省将文件复制到持久位置的时间和资源。

    import os
    from django.core.files import uploadedfile

    file = request.FILES["import_file"]
    new_path = '/tmp/import_file'
    if isinstance(file, uploadedfile.TemporaryUploadedFile):
        os.rename(file.file.name, new_path)
    else:    # Deal with InMemoryUploadedFile
        with open(new_path, 'wb') as f:
            for chunk in file.chunks():
                f.write(chunk)
    task_id = importing.delay(new_path).id

【讨论】:

    猜你喜欢
    • 2012-03-22
    • 2018-10-19
    • 2015-04-12
    • 2019-11-13
    • 2021-11-22
    • 2014-03-07
    • 2018-10-01
    • 2018-01-04
    • 1970-01-01
    相关资源
    最近更新 更多