I can't write data to google sheets via python. I did everything like in Google Sheets Api example but it still doesn't work. This is my project:
from __future__ import print_function
from googleapiclient.discovery import build
from httplib2 import Http
from oauth2client import file as oauth_file, client, tools
SCOPES = ['https://www.googleapis.com/auth/spreadsheets','https://www.googleapis.com/auth/drive', 'https://www.googleapis.com/auth/drive.file']
SAMPLE_SPREADSHEET_ID = 'ID'
SAMPLE_RANGE = 'Sheet2!A1:A10'
def main():
store = oauth_file.Storage('token.json')
creds = store.get()
if not creds or creds.invalid:
flow = client.flow_from_clientsecrets('credentials.json', SCOPES)
creds = tools.run_flow(flow, store)
service = build('sheets', 'v4', http=creds.authorize(Http()))
values = {'values': [['one','two','three']]}
result = service.spreadsheets().values().append(
spreadsheetId=SAMPLE_SPREADSHEET_ID, range=SAMPLE_RANGE,
valueInputOption='RAW',
body=values).execute()
print('{0} cells updated.'.format(result.get('updatedCells')));
if __name__ == '__main__':
main()
And it gives me this errors:
C:\Users\Victor\Anaconda3\python.exe "C:/Users/Victor/Desktop/NEW try/try1.py"
Traceback (most recent call last):
File "C:/Users/Victor/Desktop/NEW try/try1.py", line 31, in <module>
main()
File "C:/Users/Victor/Desktop/NEW try/try1.py", line 27, in main
body=values).execute()
File "C:\Users\Victor\Anaconda3\lib\site-packages\googleapiclient\_helpers.py", line 130, in positional_wrapper
return wrapped(*args, **kwargs)
File "C:\Users\Victor\Anaconda3\lib\site-packages\googleapiclient\http.py", line 842, in execute
raise HttpError(resp, content, uri=self.uri)
googleapiclient.errors.HttpError: <HttpError 403 when requesting https://sheets.googleapis.com/v4/spreadsheets/1RaeZ4QpT3-ZCcIfBDKdtQJt0WDJKiLnBsB3dTC2PoGg/values/Sheet2%21A1%3AA10:append?valueInputOption=RAW&alt=json returned "Request had insufficient authentication scopes.">
Process finished with exit code 1
I pin a screenshot that prooves that i have all the permisions in the api.
Google API
Thank you in advance.
From my understanding, exit code 1 "means there was some issue / problem which caused the program to exit." Trying to debug your code, it seems like your indentation is off. Everything between lines 11 and 25 should have at least one indent so it's considered to be apart of the main() function. Like so:
from __future__ import print_function
from googleapiclient.discovery import build
from httplib2 import Http
from oauth2client import file as oauth_file, client, tools
SCOPES = ['https://www.googleapis.com/auth/spreadsheets','https://www.googleapis.com/auth/drive', 'https://www.googleapis.com/auth/drive.file']
SAMPLE_SPREADSHEET_ID = 'ID'
SAMPLE_RANGE = 'Sheet2!A1:A10'
def main():
store = oauth_file.Storage('token.json')
creds = store.get()
if not creds or creds.invalid:
flow = client.flow_from_clientsecrets('credentials.json', SCOPES)
creds = tools.run_flow(flow, store)
service = build('sheets', 'v4', http=creds.authorize(Http()))
values = {'values': [['one','two','three']]}
result = service.spreadsheets().values().append(
spreadsheetId=SAMPLE_SPREADSHEET_ID, range=SAMPLE_RANGE,
valueInputOption='RAW',
body=values).execute()
print('{0} cells updated.'.format(result.get('updatedCells')));
if __name__ == '__main__':
main()
Also, the Google Sheets API Quick Start for Python gets updated frequently, so I would try using the new code featured here. Let us know what happens after you fix the indentation or you decide to go with Google's updated code.
Related
I was try to create google sheet using python in Pycharm but I try very had didn't out bugs.
here I submit my full code and show my error result.
# [START sheets_create]
from __future__ import print_function
import google.auth
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
def create(title):
"""
Creates the Sheet the user has access to.
Load pre-authorized user credentials from the environment.
TODO(developer) - See https://developers.google.com/identity
for guides on implementing OAuth2 for the application.\n"
"""
creds = 'conof.json'
# pylint: disable=maybe-no-member
try:
service = build('sheets', 'v4', credentials=creds)
spreadsheet = {
'properties': {
'title': title
}
}
spreadsheet = service.spreadsheets().create(body=spreadsheet,
fields='spreadsheetId') \
.execute()
print(f"Spreadsheet ID: {(spreadsheet.get('spreadsheetId'))}")
return spreadsheet.get('spreadsheetId')
except HttpError as error:
print(f"An error occurred: {error}")
return error
if __name__ == '__main__':
# Pass: title
create("mysheet1")
# [END sheets_create]
This is default code I found from google sheet development site I just added here my json file from google cloud console generated. I was hard to manage to solve library error's. I am using windows platform.
And my error's
C:\Users\pc\PycharmProjects\createShee\venv\Scripts\python.exe C:/Users/pc/PycharmProjects/createShee/mumu.py
Traceback (most recent call last):
File "C:\Users\pc\PycharmProjects\createShee\mumu.py", line 37, in <module>
create("mysheet1")
File "C:\Users\pc\PycharmProjects\createShee\mumu.py", line 19, in create
service = build('sheets', 'v4', credentials=creds)
File "C:\Users\pc\PycharmProjects\createShee\venv\lib\site-packages\googleapiclient\_helpers.py", line 130, in positional_wrapper
return wrapped(*args, **kwargs)
File "C:\Users\pc\PycharmProjects\createShee\venv\lib\site-packages\googleapiclient\discovery.py", line 298, in build
service = build_from_document(
File "C:\Users\pc\PycharmProjects\createShee\venv\lib\site-packages\googleapiclient\_helpers.py", line 130, in positional_wrapper
return wrapped(*args, **kwargs)
File "C:\Users\pc\PycharmProjects\createShee\venv\lib\site-packages\googleapiclient\discovery.py", line 604, in build_from_document
http = _auth.authorized_http(credentials)
File "C:\Users\pc\PycharmProjects\createShee\venv\lib\site-packages\googleapiclient\_auth.py", line 124, in authorized_http
return credentials.authorize(build_http())
AttributeError: 'str' object has no attribute 'authorize'
Process finished with exit code 1
Please help me to solve this project.
The credential parameter of build() method can only accept the following objects:
credentials: oauth2client.Credentials or
google.auth.credentials.Credentials, credentials to be used for
authentication.
An easy way to create a credential object is to use the authentication in the Python Quickstart of Google Sheets API.
Just follow the Quickstart guide, change the scope to 'https://www.googleapis.com/auth/spreadsheets' and replace the try-except block with the try-except block in the Create a spreadsheet.
Your code should look like this:
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/spreadsheets']
def create(title):
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('sheets', 'v4', credentials=creds)
spreadsheet = {
'properties': {
'title': title
}
}
spreadsheet = service.spreadsheets().create(body=spreadsheet,
fields='spreadsheetId') \
.execute()
print(f"Spreadsheet ID: {(spreadsheet.get('spreadsheetId'))}")
return spreadsheet.get('spreadsheetId')
except HttpError as error:
print(f"An error occurred: {error}")
return error
if __name__ == '__main__':
create("mysheet1")
Output:
Notes: Make sure to install the necessary package included in the Quickstart guide, download the credential json file, save it in the same directory as your script and rename it to credentials.json
Reference:
Module discovery
Try replacing creds = 'conof.json' with
credentials = google.oauth2.credentials.Credentials.from_authorized_user_file('conof.json)
and adding the import as necessary.
You are currently passing a string to the credentials parameter in build; however, build expects you to pass a specific type of credentials object to it. You can obtain this credential object from a JSON file using the line of code above. See this answer for more detail.
I'm trying to apply filter on my google sheet using python sheets API. I'm getting this error, and there are no any hints to debug this error. My code looks like this. I tried to print the requests body, which is exactly in the same format as that suggested on API documentation(https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#setbasicfilterrequest).
My code looks like this :
from __future__ import print_function
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
import pandas as pd
import json
# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/spreadsheets']
# The ID and range of a sample spreadsheet.
SAMPLE_SPREADSHEET_ID = '1ViILuxI3MD3vT7efWYDmlo5A67dIIDJbWXh6Pm9myPQ'
SAMPLE_RANGE_NAME = 'Sheet1!A2:I'
def main():
"""Shows basic usage of the Sheets API.
Prints values from a sample spreadsheet.
"""
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())
service = build('sheets', 'v4', credentials=creds)
_filter = {
"range": {
"sheetId": 0,
"startRowIndex": 1,
"startColumnIndex": 9,
"endColumnIndex": 10
},
"criteria" : {
9 : {
"hiddenValues" : [
"Closed"
]
}
}
}
setBasicFilterRequest = {
'setBasicFilter' : {
'filter' : _filter
}
}
body = {
'requests' : [setBasicFilterRequest],
'includeSpreadsheetInResponse' : True,
}
# print(json.dumps(body, indent=4))
resp = service.spreadsheets() \
.batchUpdate(spreadsheetId="Sheet1", body=body).execute()
print(resp)
if __name__ == '__main__':
main()
I'm getting following error when I run this :
Traceback (most recent call last):
File "poll_sheets.py", line 79, in <module>
main()
File "poll_sheets.py", line 72, in main
resp = service.spreadsheets() \
File "/Users/mike/Desktop/redash/myenv/lib/python3.8/site-packages/googleapiclient/_helpers.py", line 134, in positional_wrapper
return wrapped(*args, **kwargs)
File "/Users/mike/Desktop/redash/myenv/lib/python3.8/site-packages/googleapiclient/http.py", line 920, in execute
raise HttpError(resp, content, uri=self.uri)
googleapiclient.errors.HttpError: <HttpError 404 when requesting https://sheets.googleapis.com/v4/spreadsheets/Sheet1:batchUpdate?alt=json returned "Requested entity was not found.". Details: "Requested entity was not found.">
(myenv) (base) mike#Mikes-MacBook-Pro redash %
Modification points:
When I saw your script, it seems that SAMPLE_SPREADSHEET_ID is not used.
About resp = service.spreadsheets().batchUpdate(spreadsheetId="Sheet1", body=body).execute(), it seems that you use the sheet name as the Spreadsheet ID. I think that this is the reason of your issue.
When above points are reflected to your script, it becomes as follows.
Modified script:
From:
resp = service.spreadsheets().batchUpdate(spreadsheetId="Sheet1", body=body).execute()
To:
resp = service.spreadsheets().batchUpdate(spreadsheetId=SAMPLE_SPREADSHEET_ID, body=body).execute()
Note:
When you run above modified script and the same error occurs, please confirm the Spreadsheet ID again.
Reference:
Method: spreadsheets.batchUpdate
I'm trying to understand how to work with Google Slides API,
I did everything as it was described here.
In "enable Google Slides API" I tried to choose "Desktop app" or "Web Server", but in both ways every time when I try to run quickstart.py file, I get same error:
googleapiclient.errors.HttpError: <HttpError 403 when requesting https://slides.googleapis.com/v1/presentations/1EAYk18WDjIG-zp_0vLm3CsfQh_i8eXc67Jo2O9C6Vuc?alt=json returned "Request had insufficient authentication scopes.">
This is what i have inside my quickstart.py:
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/presentations.readonly']
# The ID of a sample presentation.
PRESENTATION_ID = '1EAYk18WDjIG-zp_0vLm3CsfQh_i8eXc67Jo2O9C6Vuc'
def main():
"""Shows basic usage of the Slides API.
Prints the number of slides and elments in a sample presentation.
"""
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('slides', 'v1', credentials=creds)
# Call the Slides API
presentation = service.presentations().get(
presentationId=PRESENTATION_ID).execute()
slides = presentation.get('slides')
print('The presentation contains {} slides:'.format(len(slides)))
for i, slide in enumerate(slides):
print('- Slide #{} contains {} elements.'.format(
i + 1, len(slide.get('pageElements'))))
if __name__ == '__main__':
main()
Updated:
Whole error msg looks like this:
Traceback (most recent call last):
File "/Users/A/PycharmProjects/PyProjects/quickstart.py", line 54, in <module>
main()
File "/Users/A/PycharmProjects/PyProjects/quickstart.py", line 44, in main
presentationId=PRESENTATION_ID).execute()
File "/Users/A/PycharmProjects/PyProjects/venv/lib/python3.7/site-packages/googleapiclient/_helpers.py", line 134, in positional_wrapper
return wrapped(*args, **kwargs)
File "/Users/A/PycharmProjects/PyProjects/venv/lib/python3.7/site-packages/googleapiclient/http.py", line 907, in execute
raise HttpError(resp, content, uri=self.uri)
googleapiclient.errors.HttpError: <HttpError 403 when requesting https://slides.googleapis.com/v1/presentations/1EAYk18WDjIG-zp_0vLm3CsfQh_i8eXc67Jo2O9C6Vuc?alt=json returned "Request had insufficient authentication scopes.">
Hello I have stumbled upon the same issue it is easily solvable, you just have to approve it manually.
https://developers.google.com/people/quickstart/python#step_1_turn_on_the
So press the Enable the People API button and it should open a new window where you have to login manually first time for the approval hope it helps.
$ pip3 list | grep googl
google-api-python-client 1.7.9
google-auth 1.6.3
google-auth-httplib2 0.0.3
google-auth-oauthlib 0.4.0
I can successfully list files shared to me. But I get "File not found" error when I try to download an existing file by its id. How to download a file by its id?
Script to list files
from __future__ import print_function
import pickle
import os.path
import io
import sys
from googleapiclient.discovery import build
from googleapiclient.http import MediaIoBaseDownload
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/drive.metadata.readonly']
TOKEN_FILE = 'tockenRead.pickle'
def main():
"""Shows basic usage of the Drive v3 API.
Prints the names and ids of the first 10 files the user has access to.
"""
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_FILE):
with open(TOKEN_FILE, '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()
# Save the credentials for the next run
with open(TOKEN_FILE, 'wb') as token:
pickle.dump(creds, token)
service = build('drive', 'v3', credentials=creds)
# Call the Drive v3 API
results = service.files().list(
q="mimeType != 'application/vnd.google-apps.folder'",
pageSize=10,
fields="nextPageToken, files(id, name)"
).execute()
items = results.get('files', [])
if not items:
print('No files found.')
else:
print('Files:')
for item in items:
print(u'{0} ({1})'.format(item['name'], item['id']))
if __name__ == '__main__':
main()
Result
$ python3 list_files.py
Files:
20140810_125633.mp4 (1SwYm5Z1zPczZnDulmsbA9wrEJ-JT-hwE)
Getting started (0B3K2QXOGSOFRc3RhcnRlcl9maWxl)
Script to download file with id 1SwYm5Z1zPczZnDulmsbA9wrEJ-JT-hwE
from __future__ import print_function
import pickle
import os.path
import io
import sys
from googleapiclient.discovery import build
from googleapiclient.http import MediaIoBaseDownload
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/drive.file']
TOKEN_FILE = 'tokenWrite.pickle';
def downloadFile(driveService, fileId):
request = driveService.files().get_media(fileId=fileId)
fh = io.BytesIO()
downloader = MediaIoBaseDownload(fh, request)
done = False
while done is False:
status, done = downloader.next_chunk()
print ("Download %d%%." % int(status.progress() * 100))
def main():
"""Shows basic usage of the Drive v3 API.
Prints the names and ids of the first 10 files the user has access to.
"""
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_FILE):
with open(TOKEN_FILE, '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()
# Save the credentials for the next run
with open(TOKEN_FILE, 'wb') as token:
pickle.dump(creds, token)
service = build('drive', 'v3', credentials=creds)
downloadFile(service, '1SwYm5Z1zPczZnDulmsbA9wrEJ-JT-hwE')
if __name__ == '__main__':
main()
Error
$ python3 download_files.py
Please visit this URL to authorize this application: https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=619229308650-91gkhdgo7v0jbt6df1phahmq868eb7gd.apps.googleusercontent.com&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2F&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.file&state=4mP9kgVJQD4ETOu5JjIRQFBLcyViAG&access_type=offline&code_challenge=ybCzMgZ2SOXdrpZZYn1dq9nSJk8wMtLo7Deg_Xix9So&code_challenge_method=S256
Traceback (most recent call last):
File "download_files.py", line 52, in <module>
main()
File "download_files.py", line 49, in main
downloadFile(service, '1SwYm5Z1zPczZnDulmsbA9wrEJ-JT-hwE')
File "download_files.py", line 21, in downloadFile
status, done = downloader.next_chunk()
File "/usr/local/lib/python3.7/site-packages/googleapiclient/_helpers.py", line 130, in positional_wrapper
return wrapped(*args, **kwargs)
File "/usr/local/lib/python3.7/site-packages/googleapiclient/http.py", line 705, in next_chunk
raise HttpError(resp, content, uri=self._uri)
googleapiclient.errors.HttpError: <HttpError 404 when requesting https://www.googleapis.com/drive/v3/files/1SwYm5Z1zPczZnDulmsbA9wrEJ-JT-hwE?alt=media returned "File not found: 1SwYm5Z1zPczZnDulmsbA9wrEJ-JT-hwE.">
How about this answer?
Reason of issue:
When I saw your scripts, I noticed that the scope of below script are different from the above script. I think that this is the reason of your issue.
At above script, https://www.googleapis.com/auth/drive.metadata.readonly is used. On the other hand, at the below script, https://www.googleapis.com/auth/drive.file is used.
The official document says about the scope of https://www.googleapis.com/auth/drive.file as follows.
View and manage Google Drive files and folders that you have opened or created with this app
This means that when your script uploads a file using the scope of https://www.googleapis.com/auth/drive.file, you can retrieve the file using the scope. But for example, when the file is manually upload to the Google Drive, the file cannot be downloaded by the scope of https://www.googleapis.com/auth/drive.file, even when the file is shared with you.
In order to download the file, how about the following workarounds?
Workaround 1:
You use the scope of https://www.googleapis.com/auth/drive or https://www.googleapis.com/auth/drive.readonly instead of https://www.googleapis.com/auth/drive.file.
Workaround 2:
If you are required to use the scope of https://www.googleapis.com/auth/drive.file, it uploads the file using the scope of https://www.googleapis.com/auth/drive.file. By this, the file can be downloaded by the scope.
Note:
When you change the scopes, please remove the file of tokenWrite.pickle and authorize the scopes again and create new tokenWrite.pickle. By this, you can use new scopes. Please be careful this.
Reference:
Scopes of Drive API, v3
If I misunderstood your question and this was not the direction you want, I apologize.
I am pretty much using the sample from google's own site
https://developers.google.com/apps-script/api/how-tos/execute
The relevant part of the sample python script is replicated below
from __future__ import print_function
from googleapiclient import errors
from googleapiclient.discovery import build
from httplib2 import Http
from oauth2client import file as oauth_file, client, tools
def main():
"""Runs the sample.
"""
SCRIPT_ID = 'ENTER_YOUR_SCRIPT_ID_HERE'
# Setup the Apps Script API
SCOPES = 'https://www.googleapis.com/auth/script.projects'
store = oauth_file.Storage('token.json')
creds = store.get()
if not creds or creds.invalid:
flow = client.flow_from_clientsecrets('credentials.json', SCOPES)
creds = tools.run_flow(flow, store)
service = build('script', 'v1', http=creds.authorize(Http()))
if __name__ == '__main__':
main()
I am getting the following error
File "test.py", line 67, in <module>
main()
File "test.py", line 22, in main
service = build('script', 'v1', http=creds.authorize(Http()))
File "C:\Users\pedxs\Anaconda2\lib\site-packages\googleapiclient\_helpers.py", line 130, in positional_wrapper
return wrapped(*args, **kwargs)
File "C:\Users\pedxs\Anaconda2\lib\site-packages\googleapiclient\discovery.py", line 232, in build
raise e
googleapiclient.errors.HttpError: <HttpError 400 when requesting https://www.googleapis.com/discovery/v1/apis/script/v1/rest returned "Request contains an invalid argument.">
I had this exact code working just a week ago. line 22 uses the discovery build function, which as I understand is sending credentials to Google's API authenticator server "https://www.googleapis.com/discovery/v1/apis/script/v1/rest". I am suspecting this is a problem on Google's side because even their sample code does not work.
I have tried creating a new Google Cloud Platform and getting a new credentials.json file. I also tried authenticating with a different email account.
i encountered same error.
i have used that code more than 1 year ago.
but suddenly i could not use since Feb-23.
so i adopted another method, and i used post request with oauth2.
i think you need your google service account renew.
i think something change with scope ui...
good luck!
■python code
from oauth2client import client
def request_to_gas():
credentials = client.OAuth2Credentials(
access_token=None,
client_id={your_client_id},
client_secret={your_client_secret},
refresh_token={your_refresh_token},
token_expiry=None,
token_uri=GOOGLE_TOKEN_URI,
user_agent=None,
revoke_uri=GOOGLE_REVOKE_URI)
credentials.refresh(httplib2.Http()) # refresh the access token
my_url = "your_google_apps_script_web_url"
myheaders = {'Authorization': 'Bearer {}'.format(credentials.access_token),
"Content-Type": "application/json"
}
response = requests.post(my_url,
data=json.dumps({
'localdate' : '2019/02/23 12:12:12'}),
headers=myheaders
)
add thins code and publish as web app.
■google apps script code
function doPost(e) {
var params = JSON.parse(e.postData.getDataAsString()); // ※
var value = params.localdate; // get python code -- 2019/02/23 12:12:12
// here is your google apps script api
do_something();
var output = ContentService.createTextOutput();
output.setMimeType(ContentService.MimeType.JSON);
output.setContent(JSON.stringify({ message: "success!" }));
return output;
}
In your situation, there are 2 patterns.
Pattern 1:
Use authorization script at Quickstart.
Sample script:
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
def main():
# Setup the Apps Script API
SCOPES = ['https://www.googleapis.com/auth/script.projects', 'https://www.googleapis.com/auth/drive']
creds = None
if os.path.exists('token.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
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(
'client_secret.json', SCOPES)
creds = flow.run_local_server()
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
service = build('script', 'v1', credentials=creds)
scriptId = "### script ID ###" # Please set this
request = {"function": "myFunction", "parameters": ["sample"], "devMode": True}
response = service.scripts().run(body=request, scriptId=scriptId).execute()
print(response)
if __name__ == '__main__':
main()
Pattern 2:
If you want to use the script in your question, please modify your script as follows. This is discussed at here and here.
Sample script:
from __future__ import print_function
from googleapiclient.discovery import build
from oauth2client import file as oauth_file, client, tools
def main():
SCOPES = ['https://www.googleapis.com/auth/script.projects', 'https://www.googleapis.com/auth/drive']
store = oauth_file.Storage('token.json')
creds = store.get()
if not creds or creds.invalid:
flow = client.flow_from_clientsecrets('client_secret.json', SCOPES)
creds = tools.run_flow(flow, store)
service = build('script', 'v1', credentials=creds)
scriptId = "### script ID ###" # Please set this
request = {"function": "myFunction", "parameters": ["sample"], "devMode": True}
response = service.scripts().run(body=request, scriptId=scriptId).execute()
print(response)
if __name__ == '__main__':
main()
Sample script of GAS side:
function myFunction(e) {
return "ok: " + e;
}
Result:
You can retrieve the following response from above both scripts.
{
"response": {
"#type": "type.googleapis.com/google.apps.script.v1.ExecutionResponse",
"result": "ok: sample"
},
"done": True
}
Note:
Before you use above scripts, please setup for using it. You can see the official document at below.
Executing Functions using the Apps Script API
Method: scripts.run
In my environment, I could confirm that above both patterns can be used. But if in your environment, those were not used, I apologize.