How to deploy a Flask app to Google Cloud (App Engine) with an application factory, and how to write the app.yaml file?

Question:

I found a similar question here but the solution did not work for me.

I have written a Flask app by following the official tutorial. I am trying to deploy it with Google App Engine. I have used Blueprints. The directory structure of my app looks like this:

app
│   .gcloudignore
│   app.yaml
│   main.py
│   requirements.txt
│   __init__.py
│
├───googleutils
│   │   utils.py
│
├───home
│   │   home.py
│   │
│   ├───static
│   ├───templates
│   │       home.html
│
├───models
│   │   Message.py
│   │   User.py
│
├───profile
│   │   profile.py
│   │
│   ├───static
│   ├───templates
│   │       edit_message.html
│   │       profile.html
│
├───sessions
│   │   sessions.py
│   │
│   ├───templates
│   │       login.html
│   │       logout.html
│   │       register.html
│
├───static
│       style.css
│
├───templates
│       layout.html
│       wrapper.html

In my app directory I have my app.yaml and requirements.txt. I used pip freeze in my venv and just chucked everything it spat out into requirements.txt.

The current Flask tutorial instructs you to start your app via command line using flask run. Hence, my application starts from __init__.py:

from flask import Flask

def create_app():
    app = Flask(__name__, instance_relative_config=True)

    # Application imports
    from .home import home
    from .sessions import sessions
    from .profile import profile

    # Blueprints
    app.register_blueprint(home.home_bp)
    app.register_blueprint(sessions.sessions_bp)
    app.register_blueprint(profile.profile_bp)

    return app

However, as noted in the question I linked above, gcloud looks for a main.py, so I added this to my root:

from app import create_app

app = create_app()

At the moment I’m just trying to get my index loaded, which is defined in home.py:

@home_bp.route('/', methods=['GET', 'POST'])
def home():
...

Here’s my app.yaml:

runtime: python39
entrypoint: gunicorn "app:create_app()"

handlers:
- url: /static
  static_dir: static

- url: /.*
  script: auto

Truth be told I have no idea how to write this file, especially for directories with variables, such as this one defined in profile.py:

@profile_bp.route('/profile/<string:user_id>', methods=['GET', 'POST'])
def profile(user_id):
...

When I run gcloud app deploy, I get a 500 Server Error when I view my site in-browser, "The server encountered an error and could not complete your request.".

What am I doing wrong?

Asked By: Tom H

||

Answers:

Well, I figured it out. My directory structure was wrong. It SHOULD be:

│   app.yaml
│   main.py
│   requirements.txt
├───app
│   │   __init__.py
│   └

Where app.yaml contains only:

runtime: python39

handlers:
- url: /.*
  script: auto

Which causes GCloud to automatically look for the main.py file containing:

from app import create_app

app = create_app()

The whole webapp works this way.

Answered By: Tom H

Does it have to be called main.py or is it calling for app = create_app()?

Answered By: abdulraoufa
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.