I'm getting an error when trying to deploy my Flask-Python code to Google App Engine. I am using PostgreSQL as my database. This is the error:
Traceback (most recent call last):
File "/env/lib/python3.6/site-packages/gunicorn/arbiter.py", line 557, in spawn_worker
worker.init_process()
File "/env/lib/python3.6/site-packages/gunicorn/workers/base.py", line 126, in init_process
self.load_wsgi()
File "/env/lib/python3.6/site-packages/gunicorn/workers/base.py", line 136, in load_wsgi
self.wsgi = self.app.wsgi()
File "/env/lib/python3.6/site-packages/gunicorn/app/base.py", line 67, in wsgi
self.callable = self.load()
File "/env/lib/python3.6/site-packages/gunicorn/app/wsgiapp.py", line 65, in load
return self.load_wsgiapp()
File "/env/lib/python3.6/site-packages/gunicorn/app/wsgiapp.py", line 52, in load_wsgiapp
return util.import_app(self.app_uri)
File "/env/lib/python3.6/site-packages/gunicorn/util.py", line 357, in import_app
__import__(module)
File "/home/vmagent/app/main.py", line 20, in <module>
SQLAlchemy.engine.url.URL(
AttributeError: 'property' object has no attribute 'url'
[2021-01-03 14:35:46 +0000] [8] [INFO] Worker exiting (pid: 8)
[2021-01-03 14:35:46 +0000] [1] [INFO] Shutting down: Master
[2021-01-03 14:35:46 +0000] [1] [INFO] Reason: Worker failed to boot.
main.py code:
from flask import Flask, redirect, url_for, render_template, request,
from flask_sqlalchemy import SQLAlchemy
import os
# Remember - storing secrets in plaintext is potentially unsafe. Consider using
# something like https://cloud.google.com/secret-manager/docs/overview to help keep
# secrets secret.
db_user = os.environ["DB_USER"]
db_pass = os.environ["DB_PASS"]
db_name = os.environ["DB_NAME"]
db_socket_dir = os.environ.get("DB_SOCKET_DIR", "/cloudsql")
cloud_sql_connection_name = os.environ["CLOUD_SQL_CONNECTION_NAME"]
pool = SQLAlchemy.create_engine(
# Equivalent URL:
# postgres+pg8000://<db_user>:<db_pass>@/<db_name>
# ?unix_sock=<socket_path>/<cloud_sql_instance_name>/.s.PGSQL.5432
SQLAlchemy.engine.url.URL(
drivername="postgresql+pg8000",
username=db_user, # e.g. "my-database-user"
password=db_pass, # e.g. "my-database-password"
database=db_name, # e.g. "my-database-name"
query={
"unix_sock": "{}/{}/.s.PGSQL.5432".format(
db_socket_dir, # e.g. "/cloudsql"
cloud_sql_connection_name) # i.e "<PROJECT-NAME>:<INSTANCE-REGION>:<INSTANCE-NAME>"
}
),
**db_config
)
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgres+psycopg2://postgres:<password>@<public ip>/flaskapp?host=/cloudsql/<instance name>'
app.debug = True
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80), unique=True)
age = db.Column(db.String(120), unique=True)
def __init__(self, name, age):
self.name = name
self.age = age
def __repr__(self):
return '<User %r>' % self.username
@app.route("/")
def home():
return render_template("home.html")
@app.route('/form')
def form():
title ="form"
return render_template("form.html", title=title)
@app.route('/success', methods=["POST"])
def success():
if request.method == 'POST':
user = User(request.form['name'],request.form['age'])
try:
db.session.add(user)
db.session.commit()
return render_template("success.html")
except:
return render_template('form.html')
else:
return redirect('/')
db.create_all()
if __name__ == "__main__":
app.run(host="127.0.0.1",port=8080, debug=True)
app.yaml code:
entrypoint: "gunicorn -b:$PORT main:app"
env: flex
runtime: python
runtime_config:
python_version: 3
env_variables:
DB_USER: postgres
DB_PASS: <password>
DB_NAME: flaskapp
DB_SOCKET_DIR: /cloudsql
CLOUD_SQL_CONNECTION_NAME: <instance name>
beta_settings:
cloud_sql_instances: <instance name>
requirements.txt code:
click==7.1.2
Flask==1.1.2
Flask-SQLAlchemy==2.4.4
itsdangerous==1.1.0
Jinja2==2.11.2
MarkupSafe==1.1.1
psycopg2==2.8.6
SQLAlchemy==1.3.22
Werkzeug==1.0.1
gunicorn==19.6.0
This is guide that I've used prior to deploying the app: https://cloud.google.com/sql/docs/postgres/connect-app-engine-standard. Based on the guide, I've enabled API, installed cloud SDK, and created an SQL instance for PostgreSQL.
What am I doing wrong? Your help will be much appreciated.
db_socket_dir = os.environ.get("DB_SOCKET_DIR", "/cloudsql")
and you modified the query of the connection replacing"unix_sock": "{}/{}/.s.PGSQL.5432"
with'unix_sock': '/cloudsql/{}/.s.PGSQL.5432'
also you removed the socket dir from the query. Could you please try to use the literal example of the documentation? – Chris32db_user = os.environ["DB_USER"] File "/opt/python3.6/lib/python3.6/os.py", line 669, in __getitem__ raise KeyError(key) from None KeyError: 'DB_USER'
– MajorLazerunix_sock
andsocket dir
to the code. – MajorLazerDB_USER
environment variable, while you haveCLOUD_SQL_USERNAME
defined on your app.yaml file. Change it in either the main.py code relevant entry or on the app.yaml file. But you'll need to make all the environment variable names (related to db username, db password, db name and connection string) to have an unified criteria and coherence on both your app.yaml file and application code. – Daniel Ocando