使用 Elastic Beanstalk 部署 Flask 应用程序时遇到问题

Posted

技术标签:

【中文标题】使用 Elastic Beanstalk 部署 Flask 应用程序时遇到问题【英文标题】:Trouble deploying Flask app using Elastic Beanstalk 【发布时间】:2021-01-19 17:39:11 【问题描述】:

我正在尝试使用 Elastic Beanstalk 部署我的烧瓶应用程序。当我部署它并访问站点时,我收到“内部服务器错误”。我检查了日志,发现我收到了“ModuleNotFoundErrors”,但只有本地导入。我的文件结构如下:

backend
   -alembic
   -libs
   -common
   -models
     -user.py
   -__init__.py
   -application.py
   -requirements.txt

例如,我会收到“ModuleNotFoundError: No module named 'backend.models.user'”。出于好奇,我将导入从绝对路径更改为相对路径('backend.models.user' -> '.models.user')。现在我收到以下错误:

[Sun Oct 04 15:26:10.439457 2020] [:error] [pid 23422] [remote 127.0.0.1:12] mod_wsgi (pid=23422): Target WSGI script '/opt/python/current/app/application.py' cannot be loaded as Python module.
[Sun Oct 04 15:26:10.439510 2020] [:error] [pid 23422] [remote 127.0.0.1:12] mod_wsgi (pid=23422): Exception occurred processing WSGI script '/opt/python/current/app/application.py'.
[Sun Oct 04 15:26:10.439610 2020] [:error] [pid 23422] [remote 127.0.0.1:12] Traceback (most recent call last):
[Sun Oct 04 15:26:10.439639 2020] [:error] [pid 23422] [remote 127.0.0.1:12]   File "/opt/python/current/app/application.py", line 1, in <module>
[Sun Oct 04 15:26:10.439644 2020] [:error] [pid 23422] [remote 127.0.0.1:12]     from .config import BaseConfig
[Sun Oct 04 15:26:10.439659 2020] [:error] [pid 23422] [remote 127.0.0.1:12] ImportError: attempted relative import with no known parent package
[Sun Oct 04 15:26:11.442790 2020] [:error] [pid 23422] [remote 127.0.0.1:2576] mod_wsgi (pid=23422): Target WSGI script '/opt/python/current/app/application.py' cannot be loaded as Python module.
[Sun Oct 04 15:26:11.442839 2020] [:error] [pid 23422] [remote 127.0.0.1:2576] mod_wsgi (pid=23422): Exception occurred processing WSGI script '/opt/python/current/app/application.py'.

我还尝试将所有导入到同一目录中的模块,同时保留内置或已安装模块的导入。当我这样做时,部署工作没有内部服务器错误。关于我为什么会遇到这些问题的任何想法?

第一次更新 我返回并遵循 AWS 教程 (https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create-deploy-python-flask.html),但添加了带有 test.py 文件的 models 包,以查看是否可以使用 AWS 代码复制我的问题。在此示例中,文件结构如下所示:

~/eb-flask/
|-- virt
|-- models
   |-- test.py
|-- application.py
`-- requirements.txt

然后我重新部署了代码,得到了同样的错误:

[Sun Oct 04 23:31:28.271209 2020] [:error] [pid 3349] [remote 172.31.29.168:12] mod_wsgi (pid=3349): Target WSGI script '/opt/python/current/app/application.py' cannot be loaded as Python module.
[Sun Oct 04 23:31:28.271276 2020] [:error] [pid 3349] [remote 172.31.29.168:12] mod_wsgi (pid=3349): Exception occurred processing WSGI script '/opt/python/current/app/application.py'.
[Sun Oct 04 23:31:28.271361 2020] [:error] [pid 3349] [remote 172.31.29.168:12] Traceback (most recent call last):
[Sun Oct 04 23:31:28.271386 2020] [:error] [pid 3349] [remote 172.31.29.168:12]   File "/opt/python/current/app/application.py", line 2, in <module>
[Sun Oct 04 23:31:28.271391 2020] [:error] [pid 3349] [remote 172.31.29.168:12]     from .models import test
[Sun Oct 04 23:31:28.271406 2020] [:error] [pid 3349] [remote 172.31.29.168:12] ImportError: attempted relative import with no known parent package

第二次更新 下面是我的 Flask 应用程序的 application.py 的代码(减去几个端点),然后是 AWS Flask 教程的 application.py 的代码(我添加了额外的导入。)如第一次更新中所述,我的两个应用程序和教程的应用程序有相同的本地导入错误。

我的应用程序.py

from flask import Flask, render_template
from flask import request, session
from flask_cors import CORS
import os
from .common.api import api
from .journal_blueprint import journal_blueprint
from .manuscript_blueprint import manuscript_blueprint
from .user_blueprint import user_blueprint
from .models.decorators import requires_login
from .models.user import User
from .models.manuscript import Manuscript
from .models.journal import Journal
from .config_file import BaseConfig

application=Flask(__name__)

application.secret_key = BaseConfig.SECRET_KEY
application.config['SQLALCHEMY_DATABASE_URI'] = os.environ["DATABASE_URL"]

CORS(application)

application.register_blueprint(journal_blueprint, url_prefix='/journal')
application.register_blueprint(user_blueprint, url_prefix='/user')
application.register_blueprint(manuscript_blueprint, url_prefix='/manuscript')
application.register_blueprint(api, url_prefix="/api")


@application.route('/')
def home_template():
    return render_template('index.html')


@application.route('/login')
def login_template():
    return render_template('user/login.html')


@application.route('/register')
def register_template():
    return render_template('user/register.html')


@application.route('/search')
@requires_login
def search():
    return render_template("search.html")


if __name__ == '__main__':
    # application.run(debug=True)
    application.run()

AWS 教程应用程序.py

from flask import Flask
from .models import test

# print a nice greeting.
def say_hello(username = "World"):
    return '<p>Hello %s!</p>\n' % username

# some bits of text for the page.
header_text = '''
    <html>\n<head> <title>EB Flask Test</title> </head>\n<body>'''
instructions = '''
    <p><em>Hint</em>: This is a RESTful web service! Append a username
    to the URL (for example: <code>/Thelonious</code>) to say hello to
    someone specific.</p>\n'''
home_link = '<p><a href="/">Back</a></p>\n'
footer_text = '</body>\n</html>'

# EB looks for an 'application' callable by default.
application = Flask(__name__)

# add a rule for the index page.
application.add_url_rule('/', 'index', (lambda: header_text +
    say_hello() + instructions + footer_text))

# add a rule when the page is accessed with a name appended to the site
# URL.
application.add_url_rule('/<username>', 'hello', (lambda username:
    header_text + say_hello(username) + home_link + footer_text))

# run the app.
if __name__ == "__main__":
    # Setting debug to True enables debug output. This line should be
    # removed before deploying a production app.
    application.debug = True
    application.run()

【问题讨论】:

你的application.py是什么? 在第二次更新中添加到上面。如果您需要更多信息,请告诉我! 【参考方案1】:

在您的第二次尝试中,您错过了__init__.py。因此它应该是:

~/eb-flask/
|-- virt
|-- models
   |-- __init__.py
   |-- test.py
|-- application.py
`-- requirements.txt

在你的应用程序中它应该是(没有点):

from models import test

【讨论】:

我有 __init__.py 文件,但忘记放入上述文件结构(我的错)。但是,我确实取出了点,它起作用了!不过,在我最初的尝试中,我确实有 __init__.py 文件。我该如何解决那个问题? @SRHY15 很高兴它成功了 :-) 要接受答案,您必须按下 upvote/downvote 按钮下的“tick”按钮。【参考方案2】:

关于我最初的问题,我想出了如何解决它,但我不确定问题最初是如何产生的。通过查看sys.path,我发现我的应用程序在其中查找模块的路径是从比我的应用程序文件夹高一级的目录开始的。不知道为什么会这样。也许我在 6 个月前开始这个项目时做了一些奇怪的复制/粘贴操作。无论如何,当我在我的机器上工作时,我将不得不像这样调用我的导入from .models.users import User 而不是from models.user import User。当我在 AWS 上部署代码时,我假设路径在应用程序目录级别设置正确,因此我的相对导入不正确。我不得不改变我所有的进口来解决这个问题。我的 IDE 仍然将导入突出显示为错误,但代码现在运行良好,所以我必须弄清楚为什么会发生这种情况。

【讨论】:

以上是关于使用 Elastic Beanstalk 部署 Flask 应用程序时遇到问题的主要内容,如果未能解决你的问题,请参考以下文章

将相同的应用程序/代码部署到 Elastic Beanstalk 服务器和工作程序环境的正确方法是啥?

使用 Pallet 向 Elastic Beanstalk 部署战争

使用 MongoDB 部署 Elastic Beanstalk

使用 MongoDB 部署 Elastic Beanstalk

如何使用 TFS 2017 部署到 Elastic Beanstalk?

使用 EbCommands 部署 Laravel Aws Elastic-Beanstalk