首页 > 解决方案 > 仅在部署期间自定义模块导入错误

问题描述

我有一个非常简单的 Flask 应用程序,结构如下:

Dockerfile
requirements.txt
caller --> app.py
       --> user.py
       --> templates
       --> static

我正在初始化并运行我的Flask应用程序app.py

应用程序.py

from twilio.rest import Client 
import sys, os
...
from user import User, Anonymous   
app = Flask(__name__)
...
def create_app():
    app.run(debug=True, host='0.0.0.0', port=5005)

当我在本地运行我的应用程序时,它工作正常,但是当我尝试制作图像并运行图像时,它给了我一个错误:

  File "/caller/caller/app.py", line 11, in <module>
    from user import User, Anonymous
ModuleNotFoundError: No module named 'user'

dockerfile

FROM python:3.7.5-slim-buster


ENV INSTALL_PATH /caller
RUN mkdir -p $INSTALL_PATH

WORKDIR $INSTALL_PATH

COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
RUN pip install flask_login

COPY . .

CMD gunicorn -b 0.0.0.0:8000 --access-logfile - "caller.app"

用户.py

import uuid

class User():
  ...


class Anonymous():
  ...

你知道我该如何解决这个问题吗?这也是我的第一次Dockerfile,这可能是问题所在。构建和运行我正在做的图像docker build -t foo . && docker run -it foo

标签: pythondockerflask

解决方案


Python 的导入系统通过在解释器定义的路径列表中搜索模块来工作。您可以通过检查来查看此列表sys.path。如果您查看文档,第一项path[0]是包含您从中调用解释器的脚本的目录。

您正在通过从您在 Dockerfile 中设置gunicorn的工作目录运行来调用 Python。/caller这就是 Pythonpath[0]用于导入系统的基本目录。因此,当该行from user import User, Anonymous被击中时,Python 会尝试从 中导入它/caller,其中包含您的 Dockerfile、requirements.txt 和您复制的 /caller/ 目录(通过COPY . .在您的 Dockerfile 中)。所以包位于/caller/caller/user.py而不是/caller/user.py......导入系统没有看到它,你得到你的错误。

2种方法可以解决:

1.更改您的代码以使用相对导入。这将告诉 Python 导入系统在同一目录中查找:

from .user import User, Anonymous

2.您也可以通过更改 Dockerfile 将其内容复制/caller到容器中的/caller工作目录来修复它,而不是通过递归COPY . .调用复制所有内容。

替换COPY . .COPY caller .并更新gunicorn以调用只是app代替caller.app(因为它不再嵌套在第二个调用者目录中)。

现在,user.py 将位于/caller/user.py您的容器中,Python 导入系统会在检查时找到它sys.path[0]


推荐阅读