the use case
I have followed the flask tutorial on those pages: https://flask.palletsprojects.com/en/1.1.x/tutorial/
The project directory is the following :
/src ├── flaskr/ │ ├── __init__.py │ ├── db.py │ ├── schema.sql │ ├── auth.py │ ├── blog.py │ ├── templates/ │ │ ├── base.html │ │ ├── auth/ │ │ │ ├── login.html │ │ │ └── register.html │ │ └── blog/ │ │ ├── create.html │ │ ├── index.html │ │ └── update.html │ └── static/ │ └── style.css ├── tests/ │ ├── conftest.py │ ├── data.sql │ ├── test_factory.py │ ├── test_db.py │ ├── test_auth.py │ └── test_blog.py ├── venv/ ├── setup.py └── MANIFEST.in
run the web app
The web app works by running the script ‘run_app_prod.sh’.
the code works on my local machine (ubuntu 20.04) but not on azure web app for linux
run_app_prod.sh
#/bin/bash DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" echo current $DIR python -m pip install -e src ./test_if_db_exists.sh export FLASK_APP="flaskr:create_app()" # export FLASK_ENV=development # flask run --host=0.0.0.0 gunicorn --bind=0.0.0.0 --timeout 600 "flaskr:create_app()"
the flaskr/init.py files
# *-* coding:utf-8 *-* import os from flask import Flask from flaskr.auth import ShowLoginPage, ShowLogoutPage, ShowRegisterPage from flaskr.sca_tork_easycube_api import ShowActionsPage def create_app(test_config=None): # create and configure the app app = Flask(__name__, instance_relative_config=True) app.config.from_mapping( SECRET_KEY='dev', DATABASE=os.path.join(app.instance_path, 'flaskr.sqlite'), ) if test_config is None: # load the instance config, if it exists, when not testing app.config.from_pyfile('config.py', silent=True) else: # load the test config if passed in app.config.from_mapping(test_config) # ensure the instance folder exists try: os.makedirs(app.instance_path) except OSError: pass # a simple page that says hello @app.route('/hello') def hello(): return 'Hello, World!' # https://flask.palletsprojects.com/en/1.1.x/tutorial/database/ from . import db db.init_app(app) # https://flask.palletsprojects.com/en/1.1.x/tutorial/views/ # /register /login /logout from . import auth app.register_blueprint(auth.bp) app.add_url_rule('/auth/login', view_func=ShowLoginPage.as_view('auth.login')) app.add_url_rule('/auth/logout', view_func=ShowLogoutPage.as_view('auth.logout')) app.add_url_rule('/auth/register', view_func=ShowRegisterPage.as_view('auth.register')) from . import sca_tork_easycube_api app.add_url_rule('/sca_tork_easycube_api/actions', view_func=ShowActionsPage.as_view('sca_tork_easycube_api.actions')) # index.html from . import index app.register_blueprint(index.bp) app.add_url_rule('/', endpoint='index') return app
the error message
_____ / _ __________ _________ ____ / /_ ___ / | _ __ _/ __ / | / /| | /| | / ___/ ____|__ /_____ ____/ |__| ___ > / / / A P P S E R V I C E O N L I N U X Documentation: http://aka.ms/webapp-linux Python 3.7.5 Note: Any data outside '/home' is not persisted Starting OpenBSD Secure Shell server: sshd. Site's appCommandLine: gunicorn --bind=0.0.0.0 --timeout 600 "flaskr:create_app()" App will launch in debug mode Launching oryx with: -debugAdapter ptvsd -debugPort 49494 -appPath /home/site/wwwroot -output /opt/startup/startup.sh -virtualEnvName antenv -defaultApp /opt/defaultsite -bindPort 8000 -userStartupCommand 'gunicorn --bind=0.0.0.0 --timeout 600 "flaskr:create_app()"' Oryx Version: 0.2.20200114.13, Commit: 204922f30f8e8d41f5241b8c218425ef89106d1d, ReleaseTagName: 20200114.13 Found build manifest file at '/home/site/wwwroot/oryx-manifest.toml'. Deserializing it... Build Operation ID: |4NuzYKKsZco=.40b8e078_ Writing output script to '/opt/startup/startup.sh' Found virtual environment .tar.gz archive. Removing existing virtual environment directory /antenv... Extracting to directory /antenv... Using packages from virtual environment antenv located at /antenv. Updated PYTHONPATH to ':/antenv/lib/python3.7/site-packages' [42] [INFO] Starting gunicorn 20.0.4 [42] [INFO] Listening at: http://0.0.0.0:8000 (42) [42] [INFO] Using worker: sync [45] [INFO] Booting worker with pid: 45 [45] [ERROR] Exception in worker process Traceback (most recent call last): File "/opt/python/3.7.5/lib/python3.7/site-packages/gunicorn/arbiter.py", line 583, in spawn_worker worker.init_process() File "/opt/python/3.7.5/lib/python3.7/site-packages/gunicorn/workers/base.py", line 119, in init_process self.load_wsgi() File "/opt/python/3.7.5/lib/python3.7/site-packages/gunicorn/workers/base.py", line 144, in load_wsgi self.wsgi = self.app.wsgi() File "/opt/python/3.7.5/lib/python3.7/site-packages/gunicorn/app/base.py", line 67, in wsgi self.callable = self.load() File "/opt/python/3.7.5/lib/python3.7/site-packages/gunicorn/app/wsgiapp.py", line 49, in load return self.load_wsgiapp() File "/opt/python/3.7.5/lib/python3.7/site-packages/gunicorn/app/wsgiapp.py", line 39, in load_wsgiapp return util.import_app(self.app_uri) File "/opt/python/3.7.5/lib/python3.7/site-packages/gunicorn/util.py", line 358, in import_app mod = importlib.import_module(module) File "/opt/python/3.7.5/lib/python3.7/importlib/__init__.py", line 127, in import_module return _bootstrap._gcd_import(name[level:], package, level) File "<frozen importlib._bootstrap>", line 1006, in _gcd_import File "<frozen importlib._bootstrap>", line 983, in _find_and_load File "<frozen importlib._bootstrap>", line 965, in _find_and_load_unlocked ModuleNotFoundError: No module named 'flaskr' [45] [INFO] Worker exiting (pid: 45) [42] [INFO] Shutting down: Master [42] [INFO] Reason: Worker failed to boot.
Advertisement
Answer
I had a similar error without Azure. Analyzing this issue, I suspected it was an importing issue related to Gunicorn. My solution was to append the missing directory path to the beginning of my entry application script (flaskr/init.py in your case):
import sys sys.path.append('/src/flaskr')
I don’t know if it’s a good practice, but it worked for me. Hope it helps for you too.