Azure容器应用中Docker镜像连接Azure Storage的Celery任务报错排查
问题分析与解决方案
问题根源
importlib.util.spec_from_file_location 仅支持本地文件系统路径,无法直接加载远程HTTP/HTTPS URL指向的文件。你传入的是Azure Blob的HTTPS地址,系统会把它当作本地文件路径去查找,自然抛出FileNotFoundError。
解决方案
需要先将Azure Blob中的Python文件下载到本地临时目录,再加载本地文件执行,步骤如下:
- 用django-storages提供的存储接口读取Azure Blob中的文件内容
- 将内容写入本地临时文件
- 通过临时文件路径加载模块并执行
- 执行完成后清理临时文件(可选但推荐)
修改后的Celery任务代码
import tempfile import os import importlib.util import sys import asyncio from celery import shared_task from django.core.files.storage import default_storage from myapp.models import myapp # 替换为你的实际模型路径 @shared_task(name="test_task") def test_task(myapp_id): myapp_obj = myapp.objects.get(id=myapp_id) # 取存储中的相对路径,而非完整URL python_config_path = myapp_obj.python_config_file.name # 从Azure存储读取文件内容 with default_storage.open(python_config_path, 'r') as f: file_content = f.read() # 创建临时文件保存内容 with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as temp_file: temp_file.write(file_content) temp_file_path = temp_file.name try: # 加载本地临时文件中的模块 spec = importlib.util.spec_from_file_location("myapp_module", temp_file_path) myapp_module = importlib.util.module_from_spec(spec) sys.modules["myapp_module"] = myapp_module spec.loader.exec_module(myapp_module) # 执行模块逻辑 asyncio.run(myapp_module.run( task_id = test_task.request.id )) finally: # 清理临时文件 os.unlink(temp_file_path) return f"[myapp: {myapp_id}, task_id: {test_task.request.id}]"
关键注意点
- 确保
myapp_obj.python_config_file返回的是存储中的相对路径(比如python/test.py),而非完整URL。django-storages的FileField默认存储相对路径,MEDIA_URL仅用于拼接前端访问链接,不能直接用来拼接存储路径。 - 确认Celery运行的容器/环境对系统临时目录(如
/tmp)有读写权限。 - 若文件体积较大,建议改用流式下载写入临时文件,避免一次性读取占用过多内存。
内容的提问来源于stack exchange,提问作者Adrian
相关产品推荐
相关产品推荐

