Flask,Pymongo和Mongoengine-ImportError:无法导入名称“ app”

时间:2019-01-08 15:35:18

标签: python-3.x mongodb flask pymongo mongoengine

我正在python 3上使用mongoengine作为mongodb orm运行flask应用程序。

我正在如下常规配置文件中配置mongo连接:

MONGODB_SETTINGS = {
    'db': "dbname",
    'host': "myhost",
    'port': "27017",
    # 'username': 'xxxxxx',
    # 'password': 'xxxxxx'
}

我正在创建我的mongoengine实例:db = MongoEngine(app)

但是,在我的model.py文件中,如果我不包含隐式connect命令,它将不会获取参数,并且会尝试连接到由我配置的主机插入的localhost。

因此,我添加了尝试使用配置参数的连接,如下所示:

from app.engine import app
connect(db=app.config['MONGODB_SETTINGS']['db'], host=app.config['MONGODB_SETTINGS']['host'])

class Module(Document):
    identifier = StringField()
    path = StringField()
    description = StringField()
    name = StringField()
    method = StringField()
    meta = {'collection': 'modules'}
    ...

我得到这个异常:

[2019-01-08 14:56:51 +0000] [8] [INFO] Starting gunicorn 19.9.0
[2019-01-08 14:56:51 +0000] [8] [INFO] Listening at: https://0.0.0.0:5000 (8)
[2019-01-08 14:56:51 +0000] [8] [INFO] Using worker: eventlet
[2019-01-08 14:56:51 +0000] [10] [INFO] Booting worker with pid: 10
[2019-01-08 14:56:51 +0000] [10] [ERROR] Exception in worker process
Traceback (most recent call last):
  File "/app/env/lib/python3.6/site-packages/gunicorn/arbiter.py", line 583, in spawn_worker
    worker.init_process()
  File "/app/env/lib/python3.6/site-packages/gunicorn/workers/geventlet.py", line 102, in init_process
    super(EventletWorker, self).init_process()
  File "/app/env/lib/python3.6/site-packages/gunicorn/workers/base.py", line 129, in init_process
    self.load_wsgi()
  File "/app/env/lib/python3.6/site-packages/gunicorn/workers/base.py", line 138, in load_wsgi
    self.wsgi = self.app.wsgi()
  File "/app/env/lib/python3.6/site-packages/gunicorn/app/base.py", line 67, in wsgi
    self.callable = self.load()
  File "/app/env/lib/python3.6/site-packages/gunicorn/app/wsgiapp.py", line 52, in load
    return self.load_wsgiapp()
  File "/app/env/lib/python3.6/site-packages/gunicorn/app/wsgiapp.py", line 41, in load_wsgiapp
    return util.import_app(self.app_uri)
  File "/app/env/lib/python3.6/site-packages/gunicorn/util.py", line 350, in import_app
    __import__(module)
  File "/app/engine.py", line 10, in <module>
    from app.controllers.modules import modules
  File "/app/controllers/modules.py", line 8, in <module>
    from app.domain.model import DownloadPending
  File "/app/domain/model.py", line 1, in <module>
    from app.engine import app
ImportError: cannot import name 'app'
[2019-01-08 14:56:51 +0000] [10] [INFO] Worker exiting (pid: 10)
[2019-01-08 14:56:51 +0000] [8] [INFO] Shutting down: Master
[2019-01-08 14:56:51 +0000] [8] [INFO] Reason: Worker failed to boot.

除此之外,我还有一个服务,该服务直接使用pymongo聚合将数据存储在动态命名的集合中,因此,我必须再次在该服务中包含-mongo params和connect命令。

我想知道是否有任何方法可以重用mongo params,因为它们在所有情况下都在配置文件中。

更新 这是app.engine代码(主要py):

import logging
import os
from datetime import date, timedelta

from celery.schedules import crontab
from flask import Flask
from flask import request

from app.controllers.auth import auth
from app.controllers.modules import modules
from app.controllers.companies import companies
from app.service.services import ModuleService
from flask_jwt_extended import (
    JWTManager, jwt_required
)
from flask_cors import CORS
from flask_socketio import SocketIO

from celery import Celery

import eventlet

from app.utils.JSONEncoder import JSONEncoder
from flask_mongoengine import MongoEngine


eventlet.monkey_patch()

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)


def create_app(config_name):
    _app = Flask(__name__)
    _app.config.from_pyfile('config.py', silent=True)
    return _app


def make_celery(_app):
    celery = Celery(
        _app.import_name,
        backend=_app.config['CELERY_RESULT_BACKEND'],
        broker=_app.config['CELERY_BROKER_URL']
    )
    celery.conf.update(_app.config)

    class ContextTask(celery.Task):
        def __call__(self, *args, **kwargs):
            with _app.app_context():
                return self.run(*args, **kwargs)

    celery.Task = ContextTask
    return celery


app = create_app('profile')
# app = create_app('config')

db = MongoEngine(app, config={
    'db': "dbname",
    'host': "myhost",
    'port': 27017,
})

CORS(app)

UPLOAD_FOLDER = '/app/import'

app.config['SECRET_KEY'] = 'xxxxxxxxxxxxxxxxxxxxx'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER

app.config.update(
    CELERY_BROKER_URL='redis://redis:6379/0',
    CELERY_RESULT_BACKEND='redis://redis:6379/1',
)

celery = make_celery(app)
socketio = SocketIO(app, message_queue='redis://redis:6379/2')

"""
Services initialization
"""
modules_service = ModuleService()

jwt = JWTManager(app)


@celery.task()
def do(module_name, json_input):
    (..........)


app.register_blueprint(companies)
app.register_blueprint(modules)
app.register_blueprint(auth)

if __name__ == "__main__":
    socketio.run(host='0.0.0.0', threaded=True)

这里的最佳做法是什么?

我将不胜感激

谢谢。

1 个答案:

答案 0 :(得分:0)

感谢@Danila Ganchar

我必须以避免循环依赖关系冲突和导入顺序问题的方式重构整个代码。 还使用Mongoengine的connect()命令而不是mongoengine flask扩展将数据库连接外部化到另一个类。

现在一切正常。 谢谢!