【问题标题】:How to handle relative imports with Flask and Docker?如何使用 Flask 和 Docker 处理相对导入?
【发布时间】:2020-07-27 00:38:02
【问题描述】:

问题

我有一个应用程序 - 我们称之为 foobar。它是使用 FlaskPostgreSQLdocker-compose 构建的。

它成功构建并运行。但是当我在浏览器中打开它时,我得到了以下ImportError

flask.cli.NoAppException: While importing "app.app", an ImportError was raised:

Traceback (most recent call last):
  File "/usr/local/lib/python3.8/site-packages/flask/cli.py", line 240, in locate_app
    __import__(module_name)
  File "/usr/src/app/__init__.py", line 6, in <module>
    from config import SQLALCHEMY_DATABASE_URI
ModuleNotFoundError: No module named 'config'

错误是由app/__init__.py 中的相对导入引发的:

from config import SQLALCHEMY_DATABASE_URI

我知道所有应用程序文件都已复制到容器中 - 我可以在 Flask 调试器和 ssh 中看到它们。所以这是我的问题:为什么 Flask 不检测 config.py?我该如何解决?


上下文

文件结构

foobar
├── LICENSE
├── README.md
├── app
│   ├── Dockerfile
│   ├── __init__.py
│   ├── config.py
│   └── requirements.txt
├── docker-compose.yml
└── init.sql

docker-compose.yml

version: "3.8"
services:
    app:
        build: ./app
        ports:
            - "5000:5000"
        depends_on:
            - db
    db:
        image: "postgres:13"
        volumes:
            - "./init.sql:/docker-entrypoint-initdb.d/init.sql"

/app/Dockerfile

FROM python:3.8.5-alpine
WORKDIR /usr/src/app
ENV FLASK_ENV development
ENV FLASK_APP app
ENV FLASK_RUN_HOST 0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers postgresql-dev
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
EXPOSE 5000
COPY . .
CMD ["flask", "run"]

app/init.py

import os

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

from config import SQLALCHEMY_DATABASE_URI

app = Flask(__name__)

# configure database
app.config['SQLALCHEMY_DATABASE_URI'] = SQLALCHEMY_DATABASE_URI
db = SQLAlchemy(app)
db.Model.metadata.reflect(db.engine) # automap existing tables to db.Model

class Foo(db.Model):
    __table__ = db.Model.metadata.tables['foos']

    def __repr__(self):
        return '<Foo %r>' % self.name


@app.route('/')
def hello():
    count = db.session.query(Foo).count()
    return f'Hello World! I have {count} foos stored.'


注意 - 我知道这是sys.path 的问题。 app 中的文件被复制到app 容器的工作目录中,我可以像这样在 Flask 调试器中成功导入模块:

import sys
sys.path.append('.')
from . import config

【问题讨论】:

  • 你试过from app.config import SQLALCHEMY_DATABASE_URI,或者把你的配置文件移到文件夹app之外?
  • 我试过from app.config import SQLALCHEMY_DATABASE_URI,还是不行。另外,我不想将config.py 移出app - 我最终会在app 目录中添加更多模块和文件,然后我需要相对导入才能工作。

标签: python-3.x docker flask docker-compose python-import


【解决方案1】:

我想通了 - 解决方案是在构建 Docker 映像时将 foobar 作为本地包安装。这确保了/usr/src/app 被添加到PATH,从而修复了我的相对导入。

我改变了目录结构:

foobar
├── LICENSE
├── README.md
├── app
│   ├── Dockerfile
│   ├── foobar
│   │   ├── __init__.py
│   │   ├── config.py
│   │   └── database.py
│   ├── requirements.txt
│   └── setup.py
├── docker-compose.yml
└── init.sql

我在/app/Dockerfile 中添加了以下行:

RUN ["pip", "install", "-e", "."]

【讨论】:

    猜你喜欢
    • 2014-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-26
    • 1970-01-01
    • 2013-04-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多