Why I get this error on python firebase-admin initialize_app()? - python

when I was trying to connect google firebase real time database, I got this error:
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.
Here is my code:
import firebase_admin
from firebase_admin import credentials
from firebase_admin import db
cred = credentials.Certificate('firebase-sdk.json')
firebase_admin.initialize_app(cred, {
'databaseURL': 'https://test-139a6-default-rtdb.firebaseio.com/'
})

You only need to initialize (create) the app once. When you have created the app, use get_app instead:
# The default app's name is "[DEFAULT]"
firebase_admin.get_app(name='[DEFAULT]')

You need to initialize the Admin SDK only once. You can check if the Admin SDK is already initialized using this if statement:
if not firebase_admin._apps:
firebase_admin.initialize_app(cred, {
'databaseURL': 'https://test-139a6-default-rtdb.firebaseio.com/'
})

Related

Firestore SDK hangs in production

I'm using the Firebase Admin Python SDK to read/write data to Firestore. I've created a service account with the necessary permissions and saved the credentials .json file in the source code (I know this isn't the most secure, but I want to get the thing running before fixing security issues). When testing the integration locally, it works flawlessly. But after deploying to GCP, where our service is hosted, calls to Firestore don't work properly and retry for a while before throwing 503 Deadline Exceeded errors. However, SSHing into a GKE pod and calling the SDK manually works without issues. It's just when the SDK is used in code flow that causes problems.
Our service runs in Google Kubernetes Engine in one project (call it Project A), but the Firestore database is in another project (call it project B). The service account that I'm trying to use is owned by Project B, so it should still be able to access the database even when it is being initialized from inside Project A.
Here's how I'm initiating the SDK:
from firebase_admin import get_app
from firebase_admin import initialize_app
from firebase_admin.credentials import Certificate
from firebase_admin.firestore import client
from google.api_core.exceptions import AlreadyExists
credentials = Certificate("/path/to/credentials.json")
try:
app = initialize_app(credential=credentials, name="app_name")
except ValueError:
app = get_app(name="app_name")
client = client(app=app)
Another wrinkle is that another part of our code is able to successfully use the same service account to produce Firebase Access Tokens. The successful code is:
import firebase_admin
from firebase_admin import auth as firebase_admin_auth
if "app_name" in firebase_admin._apps:
# Already initialized
app = firebase_admin.get_app(name="app_name")
else:
# Initialize
credentials = firebase_admin.credentials.Certificate("/path/to/credentials.json")
app = firebase_admin.initialize_app(credential=credentials, name="app_name")
firebase_token = firebase_admin_auth.create_custom_token(
uid="id-of-user",
developer_claims={"admin": is_admin, "site_slugs": read_write_site_slugs},
app=app,
)
Any help appreciated.
Turns out that the problem here was a conflict between gunicorn's gevents and the SDK's use of gRCP. Something related to websockets. I found the solution here. I added the following code to our Django app's settings:
import grpc.experimental.gevent as grpc_gevent
grpc_gevent.init_gevent()

How to prevent from the value error which is appeared while getting data from firestore database in Python

I'm using firebase firestore database for my KivyMD project. In the program when a button is pressed the data should be saved in the database if they doesn't exist. It work successfully. But the problem is a ValueError is appeared when the user enters an existing email address and enter another email at second time as it is not valid. What can I do to prevent it?
The Error
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.
The Code
def send_data(self, email, password):
import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore
cred = credentials.Certificate("firestore.json")
firebase_admin.initialize_app(cred)
db = firestore.client()
data = {
"Email": email,
"Password": password
}
query_email = db.collection(u'Users').where(u"Email", u"==", data["Email"]).get()
if query_email:
print('exist')
else:
print('does not exist')
db.collection(u'Users').add(data)
Based on the error message, the problem is with the following lines:
import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore
cred = credentials.Certificate("firestore.json")
firebase_admin.initialize_app(cred)
db = firestore.client()
If possible, move these lines outside of your function. You should initialize the db elsewhere and pass it to your function.
def send_data(self, email, password, db):

Using firestore in colab with python

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)

How to access Firebase Firestore from GCP Cloud Function

I am trying to access a Firebase Firestore DB from a GCP Cloud Function - the function is not part of the Firebase project - so two separate projects. When I config/init the DB I get a permissions error
def hello_world(request):
import firebase_admin
import flask
import json
from flask import request
from firebase_admin import credentials
from firebase_admin import firestore
try:
firebase_admin.initialize_app(options={
'apiKey': '<appkey>',
'authDomain': '<authdomain>',
'databaseURL': '<url>',
'projectId': '<projID>',
'storageBucket': '<bucket>',
'messagingSenderId': '<id>',
'appId': '<app ID>'
})
except:
print("DB already init")
#end db init
db = firestore.client()
# end db setup
I expect/want the result to be to initialize the DB so I can read/write to it, but I get an error:
Error: function crashed. Details:
403 Missing or insufficient permissions.
You seem to be using the app init settings for web, you need to use the sdk key instead. Go to Settings -> Services Account -> and generate your key.
Include the json file instead of those parameters. Hope this helps!

Python - Firebase DB reference error

I need to update certain node in my Firebase DB, so this is what I'm doing:
from firebase_admin import db
def update_data_in_firebase(gid, account_id, location_id, data_to_update):
firebase_url = 'saved_locations/{}/accounts/{}/locations/{}'.format(gid, account_id, location_id)
ref = db.reference(path=firebase_url)
ref.update(data_to_update)
So, the code above is what I'm trying to do to update the data in the Firebase node, but I'm getting this error:
Invalid databaseURL option: "None". databaseURL must be a non-empty URL string.
Of course, I checked out the firebase URL and it matches, so the problem is not the URL, or, I'm missing something with the path, I mean, should I use absolute insted of relative path.
As mentioned in the comments of the question, the databaseURL was not defined.
Answer:
cred = credentials.Certificate('your_config.json')
firebase_admin = firebase_admin.initialize_app(cred, {'databaseURL': 'https://your-firebase-db'})
In the main docs of Firebase, I couldn't find the error on my app initialization:
Firebase Admin Docs
But in the Realtime Database - Admin (Get Started), there is a snippet where they initialize the Firebase App defining the databaseURL

Categories

Resources