Drive API Error Python: FileNotFoundError 'credentials.json' - python

Brand new to anything regarding programming! Please treat me like I know absolutely nothing. I followed the Google Docs API quickstart for python. I am getting the error of
FileNotFoundError: [Errno 2] No such file or directory: 'credentials.json'
From my understanding, this is because the file path is incorrect, but I have no clue how to fix it. Any help is much appreciated. Here is the source code.
from __future__ import print_function
import os.path
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/documents.readonly']
# The ID of a sample document.
DOCUMENT_ID = '195j9eDD3ccgjQRttHhJPymLJUCOUjs-jmwTrekvdjFE'
def main():
"""Shows basic usage of the Docs API.
Prints the title of a sample document.
"""
creds = None
# The file token.json stores the user's access and refresh
tokens, and is
# created automatically when the authorization flow completes
for the first
# time.
if os.path.exists('token.json'):
creds = Credentials.from_authorized_user_file('token.json',
SCOPES)
# If there are no (valid) credentials available, let the user
log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.json', 'w') as token:
token.write(creds.to_json())
try:
service = build('docs', 'v1', credentials=creds)
# Retrieve the documents contents from the Docs service.
document =
service.documents().get(documentId=DOCUMENT_ID).execute()
print('The title of the document is:
{}'.format(document.get('title')))
except HttpError as err:
print(err)
if __name__ == '__main__':
main()}

I had the same issue but one step back, I didn't know how to create the credentials.json file.
Create an API Key using steps here (note that the OAuth is different than the other API keys). These same steps are outlined below with screenshots:
Open the Google Cloud console.
At the top-left, click Menu menu
APIs & Services > Credentials. Step 2 screenshot
Click +Create Credentials > OAuth client ID. step 3 screenshot
Click Application type > Desktop app. step 4 screenshot In the "Name"
field, type a name for the credential. This name is only shown in
the Google Cloud console. NOTE: Users WILL see this name the 1st
time they give permission to the app in Google's warning dialog.
step 5 screenshot
Click Create. The OAuth client created screen
appears, showing your new Client ID and Client secret. --- Before
you Click OK --- You can download the json file here. screenshot
to download the json
Click OK. The newly created credential appears under "OAuth 2.0 Client IDs."
Finally, rename the json to credentials.json and move it to the folder where your app is running from (or give your app the right path the file).

I think you need to add the absolute path to the file. Try with a variable like this.
CLIENT_SECRET_FILE = r'C:\Users\ME\client_secret.json'
Then add that to your code.
flow = InstalledAppFlow.from_client_secrets_file(
CLIENT_SECRET_FILE , SCOPES)

If you copy files/ project folders, hard coded links will be lost.
Try getting the current directory and supplying that info to the variable looking for credentials.json. (that file is in the working directory right?)
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
CURR_DIR = os.path.dirname(os.path.realpath(__file__))
credential_file=str(CURR_DIR)+'/credentials.json' #may need backslash in windows, IDK
flow = InstalledAppFlow.from_client_secrets_file(
credential_file, SCOPES)
creds = flow.run_local_server(port=0)

Related

How to bypass the browser authentication on calling google form API, which uses oauth2?

I want to automate the process of data extraction from google using pentaho, but during the execution of the script the browser is opened and asks for the selection of the gmail account for authentication, I am using OAuth authentication in my python code. The problem is that it creates the hurdle and requires human intervention to select the account for authentication.
How to avoid this either in the python code or is there another method of authentication which does not go for the browser authentication. Because in the google documentation only the authentication with the oauth2 is illustrated.
Here is the code which I am running:
from __future__ import print_function
from apiclient import discovery
from httplib2 import Http
from oauth2client import client, file, tools
from google.auth.transport.requests import Request
SCOPES = "https://www.googleapis.com/auth/forms.responses.readonly"
DISCOVERY_DOC = "https://forms.googleapis.com/$discovery/rest?version=v1"
store = file.Storage('token.json')
creds = None
if not creds or creds.invalid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
print("need to open browser for authentication")
flow = client.flow_from_clientsecrets('client_secrets.json', SCOPES)
creds = tools.run_flow(flow, store)
service = discovery.build('forms', 'v1', http=creds.authorize(
Http()), discoveryServiceUrl=DISCOVERY_DOC, static_discovery=False)
# Prints the responses of your specified form:
form_id = '<form_id>'
result = service.forms().responses().list(formId=form_id).execute()
print(result)
here is the image of browser which opens during the execution of the script
enter image description here
have also been on this same issue for some days now...and am finding it difficult understand why google has to seek for authentication after i have generated an API Key

Using Google Sheets API in Cloud Functions in Python [duplicate]

I'm hoping to use the Google Sheets API in a cloud function, which will run from my account's default service account, and I'm working in Python. However, I've only ever authenticated the Sheets library locally, using this bit of code:
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
def gen_creds(path_to_secret: str, rw_vs_ro: str):
"""
Generate the needed credentials to work with the Sheets v4 API based on your secret
json credentials file.
:param path_to_secret: The file path to your credentials json file
:param rw_vs_ro: A string, 'r_o' or 'r_w', representing whether creds should be readonly or readwrite
:return: The built service variable
"""
if rw_vs_ro == 'r_o':
scopes = ['https://www.googleapis.com/auth/spreadsheets.readonly']
creds_nm = 'readonly_token.json'
else:
scopes = ['https://www.googleapis.com/auth/spreadsheets']
creds_nm = 'readwrite_token.json'
creds = None
# The file token.json stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists(creds_nm):
creds = Credentials.from_authorized_user_file(creds_nm, scopes)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
path_to_secret, scopes)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open(creds_nm, 'w') as token:
token.write(creds.to_json())
return build('sheets', 'v4', credentials=creds)
And I'm not entirely sure how to translate this to something that a cloud function would understand, as the cloud function won't be running as me, and lacks the same type of os path that I have access to locally. Would appreciate any insight into what the translation process looks like here--I was only able to find examples in JS, which wasn't perfect for what I was going for. Then, I would love to understand how to actually implement this code in a cloud function in GCP. Thanks!
When you deploy a cloud function, your main code will have access to all the files deployed within that function. This means all you need to do is include your readwrite_token.json/readonly_token.json files when deploying the package.
Once that's done, instead of simply passing the token files as strings, since the function’s directory can be different from the current working directory, you have to properly include the files as specified in this GCP Function Filesystem documentation
Also, you can't use InstalledAppFlow in the Cloud Function environment since this flow is meant for desktop os environments so better pray for the block to never be executed or replace with a different flow.
Actually, I found a simple answer to this question in the end--it's very easy to generate these credentials in GCP for Python! The exact replacement method for gen_creds is:
import google.auth
from googleapiclient.discovery import build
def gen_creds(rw_vs_ro: str):
"""
Generate the service credentials to be used to query a google sheet
:param rw_vs_ro: A string, 'r_o' or 'r_w', representing whether creds should be readonly or readwrite
:return: The built service variable
"""
if rw_vs_ro == 'r_o':
scopes = ['https://www.googleapis.com/auth/spreadsheets.readonly']
if rw_vs_ro == 'r_w':
scopes = ['https://www.googleapis.com/auth/spreadsheets']
creds, project = google.auth.default(scopes=scopes)
service = build('sheets', 'v4', credentials=creds)
return service
Hope this is as helpful to others as it is to me!

Create Sheets API Authentication in Cloud Function with Python

I'm hoping to use the Google Sheets API in a cloud function, which will run from my account's default service account, and I'm working in Python. However, I've only ever authenticated the Sheets library locally, using this bit of code:
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
def gen_creds(path_to_secret: str, rw_vs_ro: str):
"""
Generate the needed credentials to work with the Sheets v4 API based on your secret
json credentials file.
:param path_to_secret: The file path to your credentials json file
:param rw_vs_ro: A string, 'r_o' or 'r_w', representing whether creds should be readonly or readwrite
:return: The built service variable
"""
if rw_vs_ro == 'r_o':
scopes = ['https://www.googleapis.com/auth/spreadsheets.readonly']
creds_nm = 'readonly_token.json'
else:
scopes = ['https://www.googleapis.com/auth/spreadsheets']
creds_nm = 'readwrite_token.json'
creds = None
# The file token.json stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists(creds_nm):
creds = Credentials.from_authorized_user_file(creds_nm, scopes)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
path_to_secret, scopes)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open(creds_nm, 'w') as token:
token.write(creds.to_json())
return build('sheets', 'v4', credentials=creds)
And I'm not entirely sure how to translate this to something that a cloud function would understand, as the cloud function won't be running as me, and lacks the same type of os path that I have access to locally. Would appreciate any insight into what the translation process looks like here--I was only able to find examples in JS, which wasn't perfect for what I was going for. Then, I would love to understand how to actually implement this code in a cloud function in GCP. Thanks!
When you deploy a cloud function, your main code will have access to all the files deployed within that function. This means all you need to do is include your readwrite_token.json/readonly_token.json files when deploying the package.
Once that's done, instead of simply passing the token files as strings, since the function’s directory can be different from the current working directory, you have to properly include the files as specified in this GCP Function Filesystem documentation
Also, you can't use InstalledAppFlow in the Cloud Function environment since this flow is meant for desktop os environments so better pray for the block to never be executed or replace with a different flow.
Actually, I found a simple answer to this question in the end--it's very easy to generate these credentials in GCP for Python! The exact replacement method for gen_creds is:
import google.auth
from googleapiclient.discovery import build
def gen_creds(rw_vs_ro: str):
"""
Generate the service credentials to be used to query a google sheet
:param rw_vs_ro: A string, 'r_o' or 'r_w', representing whether creds should be readonly or readwrite
:return: The built service variable
"""
if rw_vs_ro == 'r_o':
scopes = ['https://www.googleapis.com/auth/spreadsheets.readonly']
if rw_vs_ro == 'r_w':
scopes = ['https://www.googleapis.com/auth/spreadsheets']
creds, project = google.auth.default(scopes=scopes)
service = build('sheets', 'v4', credentials=creds)
return service
Hope this is as helpful to others as it is to me!

"Error 403: access_denied" from Google authentication web api despite google account being owner

I'm using the default code provided from google here, and I don't quite understand why its not working. The code outputs the prompt Please visit this URL to authorize this application: [google login URL]. When attempting to log in with the account designated as owner of the script under the google developers console I get a Error 403: access_denied error with the message The developer hasn’t given you access to this app. It’s currently being tested and it hasn’t been verified by Google. If you think you should have access, contact the developer [the email I just tried to log in with].
from __future__ import print_function
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/spreadsheets.readonly']
# The ID and range of a sample spreadsheet.
SAMPLE_SPREADSHEET_ID = '1vrZpCGW58qCCEfVXoJYlwlulraIlfWI2SmFXa1iPtuU'
SAMPLE_RANGE_NAME = 'Class Data!A2:E'
def main():
"""Shows basic usage of the Sheets API.
Prints values from a sample spreadsheet.
"""
creds = None
# The file token.pickle stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'Google_API_Key.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
service = build('sheets', 'v4', credentials=creds)
# Call the Sheets API
sheet = service.spreadsheets()
result = sheet.values().get(spreadsheetId=SAMPLE_SPREADSHEET_ID,
range=SAMPLE_RANGE_NAME).execute()
values = result.get('values', [])
if not values:
print('No data found.')
else:
print('Name, Major:')
for row in values:
# Print columns A and E, which correspond to indices 0 and 4.
print('%s, %s' % (row[0], row[4]))
def PrintToSheets():
main()
To fix this issue for me was this simple:
Go to https://console.developers.google.com/
On the top left beside the words "Google APIs" click the project dropdown on the right
Ensure that your correct project is selected
Click "OAuth consent screen" on the left side of the screen (below "Credentials")
If you have not created a consent screen, do that first
Under "Test users" there is a button called "+ ADD USERS"
Type the email of the account you will be testing with, press enter, then click save.
It should work now!
It seems like they updated this recently because last year I did not have to do this.
The error message you are getting is related to the fact that your application has not been verified yet.
As mentioned in that link all applications that access google APIs using sensitive scopes need to go though googles verification process. Normal you are given a grace period of 100 users accessing your application before your application will be locked down and you wont be able to authorize anymore users until you verify your application it sounds like you may have hit that point.
Your only options would be to go though the verification process or to create a whole new project on Google developer console and use that client id instead as the one you are using is currently locked for additional users.
Update Change
A change has been implemented on Google Developer console. You must now authorize users / testers to access your application before it has gone through the verification process. If you go to the Google developer console for your project, under consent screen you will find the following section
You can add tests users here, however you can not remove them and you can only add 100 of them so use it wisely.

Failing to load token.pickle of google api calendar in python when deployed on to docker container

I'm trying to make a call to the google calendar api and retrieve the holiday events. I am using an api call to google calendar, works fine on my local, but when i host it on docker container its not working.
from __future__ import print_function
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
SCOPES = ['https://www.googleapis.com/auth/contacts.readonly']
def main():
"""
Shows basic usage of the People API.
Prints the name of the first 10 connections.
"""
creds = None
# The file token.pickle stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
service = build('people', 'v1', credentials=creds)
I am able to load in the line "creds = pickle.load(token)" on my local but not on the container. Do we need to do any settings on the container in order to access google api from the container or is there anything else that I am missing?
flow.run_local_server() is bound to localhost inside the container.
Start docker using --net=host (or docker-compose use network_mode:"host").
see full answer at https://github.com/googleapis/google-auth-library-python-oauthlib/issues/87#issuecomment-685094486

Categories