Flask app wont launch 'ImportError: cannot import name 'cached_property' from 'werkzeug' '

Flask app wont launch 'ImportError: cannot import name 'cached_property' from 'werkzeug' '

几周来我一直在开发 Flask 应用程序。我今天完成它并去部署它......现在它不会启动。

我没有添加或删除任何代码,所以假设部署过程中发生了一些变化?

无论如何,这是终端中显示的完整错误:

Traceback (most recent call last):
  File "C:\Users\Kev\Documents\Projects\Docket\manage.py", line 5, in <module>
    from app import create_app, db
  File "C:\Users\Kev\Documents\Projects\Docket\app\__init__.py", line 21, in <module>
    from app.api import api, blueprint, limiter
  File "C:\Users\Kev\Documents\Projects\Docket\app\api\__init__.py", line 2, in <module>
    from flask_restplus import Api
  File "C:\Users\Kev\.virtualenvs\Docket-LasDxOWU\lib\site-packages\flask_restplus\__init_
_.py", line 4, in <module>
    from . import fields, reqparse, apidoc, inputs, cors
  File "C:\Users\Kev\.virtualenvs\Docket-LasDxOWU\lib\site-packages\flask_restplus\fields.
py", line 17, in <module>
    from werkzeug import cached_property
ImportError: cannot import name 'cached_property' from 'werkzeug' (C:\Users\Kev\.virtualen
vs\Docket-LasDxOWU\lib\site-packages\werkzeug\__init__.py)

这里还有提到的三个文件中的代码。

manage.py:

from apscheduler.schedulers.background import BackgroundScheduler
from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand

from app import create_app, db

app = create_app()
app.app_context().push()

manager = Manager(app)

migrate = Migrate(app, db)

manager.add_command('db', MigrateCommand)

from app.routes import *
from app.models import *

def clear_data():
    with app.app_context():
        db.session.query(User).delete()
        db.session.query(Todo).delete()
        db.session.commit()
        print("Deleted table rows!")

@manager.command
def run():
    scheduler = BackgroundScheduler()
    scheduler.add_job(clear_data, trigger='interval', minutes=15)
    scheduler.start()
    app.run(debug=True)

if __name__ == '__main__':
    clear_data()
    manager.run()

app/__init__.py:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager

from config import Config

db = SQLAlchemy()

login = LoginManager()

def create_app():
    app = Flask(__name__)
    app.config.from_object(Config)
    db.init_app(app)

    login.init_app(app)
    login.login_view = 'login'

    from app.api import api, blueprint, limiter
    from app.api.endpoints import users, todos, register
    from app.api.endpoints.todos import TodosNS
    from app.api.endpoints.users import UserNS
    from app.api.endpoints.register import RegisterNS

    api.init_app(app)

    app.register_blueprint(blueprint)

    limiter.init_app(app)

    api.add_namespace(TodosNS)
    api.add_namespace(UserNS)
    api.add_namespace(RegisterNS)

    return app

api/__init__.py:

from logging import StreamHandler
from flask_restplus import Api
from flask import Blueprint
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address

blueprint = Blueprint('api', __name__, url_prefix='/api')

limiter = Limiter(key_func=get_remote_address)
limiter.logger.addHandler(StreamHandler())

api = Api(blueprint, doc='/documentation', version='1.0', title='Docket API',
          description='API for Docket. Create users and todo items through a REST API.\n'
                      'First of all, begin by registering a new user via the registration form in the web interface.\n'
                      'Or via a `POST` request to the `/Register/` end point', decorators=[limiter.limit("50/day", error_message="API request limit has been reached (50 per day)")])

我试过重新安装 flask & flask_restplus 但没有成功。

尝试:

from werkzeug.utils import cached_property

https://werkzeug.palletsprojects.com/en/1.0.x/utils/

降级到 Werkzeug==0.16.1 解决了这个问题

https://github.com/noirbizarre/flask-restplus/issues/777#issuecomment-583235327

编辑

想补充一点,永久(长期)解决方案是移至 flask_restx,因为 flask-restplus 不再维护。

how to migrate from flask-restplus

2020 年 5 月的正确答案:flask-restplus 已死,移至 flask-restx

来自noirbizarre/flask-restplus#778 (comment)

flask-restplus work has been discontinued due to maintainers not having pypi keys. See the drop in replacement, flask-restx. It's an official fork by the maintainer team. We have already fixed the issue there

来自noirbizarre/flask-restplus#777 (comment)

No. Flask-restplus is no longer maintained. The former maintainers do not have privileges to push to pypi, and after many months of trying, we forked the project. Check out flask-restx. It's a drop in replacement and we are roadmapping, designing, and making fixes...for instance, we already patched for Werkzeug

所以真正的解决方案是转移到 flask-restx 而不是固定到旧版本的 Werkzeug。

将 Werkzeug 降级到 0.16.1

pip3 install --upgrade Werkzeug==0.16.1

如果您执行 pip3 list,您可能会看到类似这样的内容:

Flask              1.1.2
Werkzeug           0.16.1

修复这个令人痛苦的错误是为了识别在文件中安装新包后发生的事情 PipFile.lock 是做一个差异文件并找到差异:

我安装包后发现的是 werkzeug 包改变她的版本 "version": "==0.15.2" 到 "version": "= =1.0.1" 并且当尝试执行命令时 sudo docker-compose build 给我错误。

为了修复这个错误,我是这样做的:

放弃所有更改并重新开始。

停止并删除您之前的 docker

sudo docker stop $(sudo docker ps -aq)

sudo docker rm $(sudo docker ps -aq)

再次执行 docker:

sudo docker-compose build

sudo docker-compose up

进入 docker ,获取 docker 的 ID:首先按 CRTL+z 暂停 docker ,然后在终端执行

sudo docker ps

获取CONTAINER ID列的编号

execute : sudo docker exec -it 23f77dbefd57 bash for enter in terminal of the docker

现在执行你想要的包,在我的例子中是 SOAPpy,像这样

 `pipenv install SOAPpy`

在此安装之后,安装 werkzeug 包的前一个包在我的例子中是

pipenv install Werkzeug==0.15.2

写入exit并在终端中按“Enter”,关闭docker.

内的终端

如果比较文件 Pipfile.lock 具有相同的版本,这才是真正的修复。

最后的步骤是:停止、构建并再次启动 docker:

sudo docker stop $(sudo docker ps -aq)

sudo docker-compose build

sudo docker-compose up

现在又是 运行 docker:

A note to myself, I just want to remind you that you are capable of everything and not giving up so easily, remember there is always one way, it is only to connect the dots. Never give up without fighting.

这可能太奇怪了,不会发生在其他任何人身上,但是...检查您实际导入的包。我的看起来像这样:

很明显,这里的导入有些令人厌烦...删除并重新添加了正确的“werkzeug”包并且它“有效”(事实证明我仍然需要实施 other 针对这个问题提供的解决方案... :-( )

啊-但是你问:“我如何删除这样一个损坏的包?GUI 不允许我!!”。别害怕,这也发生在我身上。在 Pycharm 中,通过将鼠标悬停在设置菜单下的包名称上找到包文件位置,在文件资源管理器中转到那里,然后删除文件夹和其他类似的东西。然后使用 GUI 重新安装软件包。