如何使用Django文件存储在API和W之间共享文件

2024-04-26 22:25:20 发布

您现在位置:Python中文网/ 问答频道 /正文

目标

我想建立一个本地docker compose部署,这样我就有5个服务。你知道吗

  • Redis公司
  • 博士后
  • 兔子MQ
  • Django API公司
  • Django工人

在这个部署中,用户通过API端点上传一个文件。此端点将文件存储在模型的FileField字段中。你知道吗

在单独的事务中,用户将通过单独的端点触发异步任务。此任务将负责

  • 下载文件
  • 正在提取文件
  • 踢子任务执行intermediate processing steps
  • 将处理结果上载到数据库

intermediate processing steps不应该将任何文件上载到数据库。你知道吗

使用django的内部文件存储解决方案来下载和上传文件。这是通过与此问题无关的文件系统层次结构实现的。你知道吗

问题

我已经设法使我的本地文件系统与此配置一起工作。如果我运行redispostgresrabbitmq的后端。然后,我在本地运行API和Worker,一切正常。你知道吗

当我创建docker-compose配置并将所有内容解耦时。手术似乎中断了。在我的docker compose日志中,我看到的是:

worker_1  | [2019-10-23 22:27:34,626: WARNING/ForkPoolWorker-2] //--------------------------------------------------------------------------------
worker_1  | [2019-10-23 22:27:34,627: WARNING/ForkPoolWorker-2] // BEGINNING TASK
worker_1  | [2019-10-23 22:27:34,627: WARNING/ForkPoolWorker-2] //--------------------------------------------------------------------------------
worker_1  | [2019-10-23 22:27:34,628: WARNING/ForkPoolWorker-2] // Root Job - 183916ca-f6e6-4e7c-a997-e8f516ccf8be
worker_1  | [2019-10-23 22:27:34,628: WARNING/ForkPoolWorker-2] // Parent Job - None
worker_1  | [2019-10-23 22:27:34,628: WARNING/ForkPoolWorker-2] // Current Job - 183916ca-f6e6-4e7c-a997-e8f516ccf8be
worker_1  | [2019-10-23 22:27:34,628: WARNING/ForkPoolWorker-2] //--------------------------------------------------------------------------------
worker_1  | [2019-10-23 22:27:34,629: WARNING/ForkPoolWorker-2] // PERFORMING DATA SET PRE PROCESSING
worker_1  | [2019-10-23 22:27:34,629: WARNING/ForkPoolWorker-2] //--------------------------------------------------------------------------------
worker_1  | [2019-10-23 22:27:34,629: WARNING/ForkPoolWorker-2] {'data_set_id': 1, 'starting_node': 'Live', 'organization_id': 1}
worker_1  | [2019-10-23 22:27:34,630: WARNING/ForkPoolWorker-2] Downloading the files required to run!
worker_1  | [2019-10-23 22:27:34,645: WARNING/ForkPoolWorker-2] Downloading remote file `organizations/1/data_sets/flow_cytometry/triple_hello_world_payload.tgz`
worker_1  | [2019-10-23 22:27:34,646: WARNING/ForkPoolWorker-2] Exists: `False`
worker_1  | [2019-10-23 22:27:34,646: WARNING/ForkPoolWorker-2] ERROR occured: [Errno 2] No such file or directory: '/opt/api_webserver/media/organizations/1/data_sets/flow_cytometry/triple_hello_world_payload.tgz'.
worker_1  | [2019-10-23 22:27:34,653: INFO/ForkPoolWorker-2] Task api.versions.v1.tasks.main_task.main_task[183916ca-f6e6-4e7c-a997-e8f516ccf8be] succeeded in 0.02647909999359399s: {'iteration': 0, 'completion': 0, 'status': 'ERROR', 'message': 'Excecuting `main_task` failed!', 'error': 'Error in `main_task`: [Errno 2] No such file or directory: \'/opt/api_webserver/media/organizations/1/data_sets/flow_cytometry/triple_hello_world_payload.tgz\'.'}

如果我进入workerdocker container并检查文件系统,media目录和文件的路径不存在。
如果我进入apidocker container并检查文件系统,media目录和文件的路径确实存在。你知道吗

相关代码

我不会提供视图代码或api代码,因为api工作正常。你知道吗

上载和文件检索在workers过程中通过使用djangodefault_storage接口进行处理。你知道吗

Django's Default Storage Interface API

这个问题与worker有关,下面是一些相关的代码。你知道吗

你知道吗工人.py你知道吗

# Python Standard Libraries
import os
# Third-Party Libraries
import tempfile
# Custom
from models.data_set_model import DataSet
from tasks.helpers import download_remote_file


def download_data_set(data_set_id):
    print("Downloading the files required to run!")
    data_set = DataSet.objects.get(id=data_set_id)

    remote_file_path = data_set.file.name
    remote_file_name = os.path.basename(remote_file_path)

    temporary_directory_path = tempfile.mkdtemp()
    temporary_compressed_file_path = os.path.join(temporary_directory_path, remote_file_name)

    download_remote_file(remote_file_path, temporary_compressed_file_path)

    return temporary_compressed_file_path

你知道吗助手.py你知道吗

# Python Standard Libraries
# N/A
# Third-Party Libraries
from django.core.files.storage import default_storage
# CustomLibraries
# N/A


def download_remote_file(remote_file_path, local_file_path):
    print(f"Downloading remote file `{remote_file_path}`")
    print(f"Exists: `{default_storage.exists(remote_file_path)}`")
    remote_file_contents = None
    with default_storage.open(remote_file_path) as remote_file_handle:
        print("Reading file contents")
        remote_file_contents = remote_file_handle.read()

    print(f"Placing remote file contents into `{local_file_path}`")
    with open(local_file_path, "wb") as local_file_handle:
        local_file_handle.write(remote_file_contents)

悬而未决的问题

  • 我做错什么了?你知道吗
  • 从API的文件存储系统下载worker上的文件的惯用方法是什么?你知道吗
  • default_storage.open()命令不应该指向API的文件系统并能够下载它吗
    • 如果没有,我可以在worker上进行哪些配置来支持它?你知道吗
  • 这仅仅是因为文件系统是共享的,而发生这种情况的原因是因为docker-compose将这些文件分解到不同的环境中吗?你知道吗

Tags: 文件pathimportapiiddefaultdataremote
1条回答
网友
1楼 · 发布于 2024-04-26 22:25:20

如果您在docker compose中,只需在api和worker之间创建一个共享docker卷,并将其装载到两个容器中的一个已知点,如/mnt/share。确保将文件保存在API中,然后工作程序可以使用相同的模型访问它们,因为设置(例如MEDIA_ROOT)将把API和工作程序都指向/mnt/share。你知道吗

相关问题 更多 >