I have a Flask app that uses Cloud Firestore for some functions. I am using the Firestore-Admin library which works fine, but I assume I placed its initializing code wrongly. My knowledge about how Flask apps work is limited so I just simply added the following code to my app.py:
cred = credentials.Certificate('key.json')
fault_app = firebase_admin.initialize_app(cred)
db = firestore.client()
While the code works, my question is that is it a proper solution to initialize the Firestore? Does this solution fits into the lifecycle of a Flask app? I already tried to init the Firestore directly from the methods that use it, but that made server errors because the amount of initializations.
Below Example Might Help you :
import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore
from flask import Flask
app = Flask(__name__)
cred = credentials.Certificate("key.json")
firebase_admin.initialize_app(cred)
db = firestore.client()
#app.route('/getdata')
def user_data():
#getting the docs
users_ref = db.collection('Demo')
docs = users_ref.get()
for doc in docs:
print('{} => {}'.format(doc.id, doc.to_dict()))
return "Recorded Printed"
if __name__ == '__main__':
app.run()
Looks reasonable to me. It's the same approach taken in this tutorial.
Related
i'm trying to use firebase in colab with Python. But there is unsolvable error,
so i need some help.
import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore
cred = credentials.Certificate('/content/myKey.json')
firebase_admin.initialize_app(cred) # error in this line
db = firestore.client()
ValueError: : The default Firebase app already exists. This means you called initialize_app() more than once without providing an app name as the second argument. In most cases you only need to call initialize_app() once. But if you do want to initialize multiple apps, pass a second argument to initialize_app() to give each app a unique name.
What can i do for solving this problem?
i also found similar answer with this, so i tried some many tips in there, like below.
import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore
if not firebase_admin._apps:
cred = credentials.Certificate('/content/foodle-94e80-firebase-adminsdk-zr21t- f02504e9fb.json')
firebase_admin.initialize_app(cred)
else:
app = firebase_admin.get_app()
db = firestore.client(app) # new error in this line
but new error is confusing me.
DefaultCredentialsError: Could not automatically determine credentials. Please set GOOGLE_APPLICATION_CREDENTIALS or explicitly create credentials and re-run the application. For more information, please see https://cloud.google.com/docs/authentication/getting-started
What can i do?
Looks like there's a default instance of the Firebase app getting initialized somewhere. When the default instance gets created, it uses GOOGLE_APPLICATION_CREDENTIALS instead of the credentials you pass in manually.
You can either provide GOOGLE_APPLICATION_CREDENTIALS to the script, or ignore the default instance of the firebase app and create an explicitly named one.
To create an explicitly named app, change your code to provide a name:
import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore
cred = credentials.Certificate('/content/myKey.json')
firebase_admin.initialize_app(credential=cred, name='myApp')
db = firestore.client()
To provide GOOGLE_APPLICATION_CREDENTIALS and use the default app:
If you're running your python script from the console, you can provide a value for that by running
export GOOGLE_APPLICATION_CREDENTIALS='/content/myKey.json'
In colab, you need to add this to your script:
import os
os.environ["GOOGLE_APPLICATION_CREDENTIALS"]="/content/myKey.json"
After this you can run your second example.
(To get the credentials JSON go to this page, select your firebase-adminsdk service account, click 'ADD KEY', 'Create new key', select JSON as your option and download the resulting file.)
In my case it worked with
cred = credentials.Certificate("/content/drive/My Drive/Colab Notebooks/LALALA.json")
firebase_admin.initialize_app(cred)
I would like to save an rdflib.Graph into the session dictionary within my Flask application as I need to access it from other route functions. The code is as follows.
from rdflib import Graph
from flask import Flask, session
import os
app = Flask(__name__)
UPLOAD_FOLDER = 'static/uploads'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config["allowed_file_extensions"] = ["ttl"]
app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 0
app.secret_key = os.urandom(24)
class API:
def __init__(self):
app.run(host="127.0.0.1", port="5000", threaded=True, debug=True)
#app.route("/")
def validate_RDF():
# saving graph to session
graph = Graph().parse("valid_mapping.ttl", format="ttl")
session["graph"] = graph
return "testing"
if __name__ == "__main__":
# start api
API()
Which outputs the following.
TypeError: Object of type 'Graph' is not JSON serializable
Any advice would be greatly appreciated.
As a rdf graph can be large, it is anyway not a good idea to try to store it in the session in my opinion. You should rather use some kind of triple store to manage your rdf information (like a web site is using a database to store information. See for instance RDFlib 'on disk' store for a store on your web server disk, or for production you would even use a triple store hosted elsewhere.
I've been making api with flask on Google App Engine and When I send request to this app from browser after deploy, I got 502 error. I'm sure this error is caused by credential of GCP by "gcloud app logs tail -s test" but The path of credential Json file and file name seems OK . I have googled and I tried every articles I have found there but could not solve.
I have already done export GOOGLE_APPLICATION_CREDENTIALS="/home/user/secret_key/bq.json"
Could anyone tell me the solution??
If there is lack of any info , please let me know . Thank you .
besides, my api function is getting luid parameter over http request and run SQL with that luid and if the row of the luid has data in cv_date column in BigQuery, it returns True to client.
【The result of "gcloud app logs tail -s test"】
File "/env/lib/python3.7/site-packages/google/auth/_default.py", line 97, in load_credentials_from_file "File {} was not found.".format(filename) google.auth.exceptions.DefaultCredentialsError: File /home/user/secret_key/bq.json was not found.
【/home/user/api_dev/main.py】
from flask import Flask,request
from google.cloud import bigquery
import os
credentials_json = '/home/user/secret_key/bq.json'
os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = credentials_json
client = bigquery.Client()
app = Flask(__name__)
#app.route('/')
def get_request():
request_luid = request.args.get('luid') or ''
query = """
SELECT EXISTS(SELECT cv_date FROM `test-266110.conversion_log.conversion_log_202008*` t WHERE request_luid = p.luid)
"""
query_res = client.query(query)
return query_res
if __name__ == "__main__":
app.run()
【Remove the codes for BigQuery except import library and variables】
*This code works well and returns luid you input on url parameter
from flask import Flask, request
from google.cloud import bigquery
import os
credentials_json = '/home/user/secret_key/bq.json'
os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = credentials_json
app = Flask(__name__)
#app.route('/')
def get_request():
request_luid = request.args.get('luid') or ''
return request_luid
if __name__ == "__main__":
app.run()
I'd recommend reading through the auth docs.
https://cloud.google.com/docs/authentication/production talks about service account interactions in a bit more detail. You likely don't need to pass in your credentials in the live app. You can simply set the GOOGLE_APPLICATION_CREDENTIALS when you're running locally to use the credentials, but you don't need to set it in production.
The issue is that the path you've specified (/home/user/secret_key/bq.json) is only valid for your development environment, and either not included in your production deployment at all or the absolute path to the file in the deployed app is different.
I want to keep track of metrics in my flask application using the lib prometheus_flask_exporter.
For what i could understand this lib already tracks default metrics in the /metrics endpoint.
But when i try to access the http://localhost:5000/metrics I get 404 Not Found.
So i tried to set a histogram metric on the user_list, but i get the same 404 not Found when i try to access the http://localhost:5000/metrics
init.py:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flasgger import Swagger
from flask_caching import Cache
from prometheus_flask_exporter import PrometheusMetrics
app = Flask(__name__)
app.debug = True
app.config.from_object('dev_maintenance.yaml_config_loader')
cache = Cache(app)
db = SQLAlchemy(app)
swagger = Swagger(app)
metrics = PrometheusMetrics(app)
import dev_maintenance.mesos_callback
import dev_maintenance.db_model
import dev_maintenance.active_directory
import dev_maintenance.user_list
import dev_maintenance.audit
import dev_maintenance.machines
import dev_maintenance.yaml_config_loader
import dev_maintenance.roles
import dev_maintenance.user_details
if __name__ == '__main__':
app.run(debug=True)
user_list.py
from dev_maintenance import app
from flask import jsonify, request
from flask_simpleldap import LDAP
from flask_jwt_extended import jwt_required
from dev_maintenance import metrics
ldap = LDAP(app)
#app.route('/api/user', methods=['GET'])
#metrics.do_not_track()
#metrics.histogram('requests_by_status_and_path', 'Request latencies by status and path',
labels={'status': lambda r: r.status_code, 'path': lambda: request.path})
def user_list():
user_list = []
users = ldap.get_group_members('ship_crew')
for user in users:
user_list.append(str(user, encoding='utf-8').split(",")[0].split("=")[1])
return jsonify(user_list)
Do i need to create a /metrics route? Because in the git documentation does not say anything about that, so i suppose this is already set behind the scenes.
Instead of "app.run(debug=True)" use "app.run(debug=False)". debug=True was breaking things.
From:https://github.com/rycus86/prometheus_flask_exporter/blob/master/README.md
Please note, that changes being live-reloaded, when running the Flask app with debug=True, are not going to be reflected in the metrics. See https://github.com/rycus86/prometheus_flask_exporter/issues/4 for more details.
Alternatively - since version 0.5.1 - if you set the DEBUG_METRICS environment variable, you will get metrics for the latest reloaded code. These will be exported on the main Flask app. Serving the metrics on a different port is not going to work most probably - e.g. PrometheusMetrics.start_http_server(..) is not expected to work.
I am a first time user of pythonanywhere
I first started by doing a git clone of my code from github through the bash console. I did not use a virtual environment. My WSGI app was invoked in my app.py file. Also, my code uses sqlalchemy to interact with my database.
Basically, the flask app was like a custom api that returned JSON for GET and POST requests and I am having trouble viewing the JSON output. I am not sure what exactly I am doing wrong or missing.
Code in app.py file:
#!flask/bin/python
from flask import Flask
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy_declarative import Base, Quote
from flask import request
from flask import abort
import json
#connect to database
engine = create_engine("sqlite:///quotes.db")
Base.metadata.bind = engine
DBSession = sessionmaker(bind=engine)
session = DBSession()
app = Flask(__name__)
#app.route("/trumptext/api/quotes", methods=["GET"])
def get_quotes():
quoteList = session.query(Quote).all()
result = []
for q in quoteList:
my_dict = {}
my_dict["id"] = q.id
my_dict["quote"] = q.quote
result.append(my_dict)
return json.dumps(result,ensure_ascii=False).encode('utf8')
#app.route("/trumptext/api/quotes", methods=["POST"])
def add_quote():
if not request.json or not "quote" in request.json:
abort(400)
new_quote = request.json["quote"]
q = Quote(quote=new_quote)
session.add(q)
session.commit()
quoteList = session.query(Quote).all()
last = quoteList[-1]
result = []
my_dict = {}
my_dict["id"] = last.id
my_dict["quote"] = last.quote
result.append(my_dict)
return json.dumps(result,ensure_ascii=False).encode('utf8'), 201
if __name__ == "__main__":
app.run()
Also, code in /var/www/nnelson_pythonanywhere_com_wsgi.py:
import os
import sys
path = '/home/nnelson/trumptextapi'
if path not in sys.path:
sys.path.append(path)
from app import app as application
If I enter something like :
http://nnelson.pythonanywhere.com/trumptext/api/quotes (to perform a GET request)
It should ideally return all the quotes stored in the quotes.db database in JSON format, however all I get it output that looks like this: [] I tested my code on localhost using the curl tool and it works just fine. I am having trouble hosting it though
Any help is appreciated.
You're using a relative path to your database, so it's probably looking at a database that you don't expect. Use a full path to the database or make it relative to the path of your app.py file so that you know where it's getting the database from.