I'm trying to make an application that uses Google Drive API. I am converting my python file to an executable using PyInstaller. I ran the .exe file generated from the most basic python script and I got an error that says
pkg_resources.DistributionNotFound: The 'google-api-python-client' distribution was not found and is required by the application
My code doesn't even use 'google-api-python-client', yet I installed it in my anaconda environment but I am still facing the same issue.
I am adding the code for reference:-
import pickle
import os
from googleapiclient.discovery import build
from google.auth.transport.requests import Request
def Create_Service(client_secret_file, api_name, api_version, *scopes):
print(client_secret_file, api_name, api_version, scopes, sep='-')
CLIENT_SECRET_FILE = client_secret_file
API_SERVICE_NAME = api_name
API_VERSION = api_version
SCOPES = [scope for scope in scopes[0]]
print(SCOPES)
cred = None
pickle_file = f'token_{API_SERVICE_NAME}_{API_VERSION}.pickle'
print(pickle_file)
if os.path.exists(pickle_file):
with open(pickle_file, 'rb') as token:
cred = pickle.load(token)
if not cred or not cred.valid:
if cred and cred.expired and cred.refresh_token:
cred.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(CLIENT_SECRET_FILE, SCOPES)
cred = flow.run_local_server(port=0)
with open(pickle_file, 'wb') as token:
pickle.dump(cred, token)
try:
service = build(API_SERVICE_NAME, API_VERSION, credentials=cred)
print(API_SERVICE_NAME, 'service created successfully')
return service
except Exception as e:
print('Unable to connect.')
print(e)
return None
s=Create_Service('client_secret_kc.json','drive','v3',['https://www.googleapis.com/auth/drive'])
The pyinstaller code I used to convert it into .exe is as follows
pyinstaller -c -F --add-data "client_secret_kc.json;." Google.py
NB- Google.py is the name of the python script gien above.
Thank you for helping.
Related
I've written a script to add events to Google calendar using the Google Calendar API for python. It works perfectly when ran as just a python script but after making it an exe with pyinstaller it fails to create a serivce object.
Code for creating service object:
def create_service(client_secret_file, api_name, api_version, *scopes, prefix=''):
CLIENT_SECRET_FILE = client_secret_file
API_SERVICE_NAME = api_name
API_VERSION = api_version
SCOPES = [scope for scope in scopes[0]]
cred = None
working_dir = os.getcwd()
token_dir = 'token files'
pickle_file = f'token_{API_SERVICE_NAME}_{API_VERSION}{prefix}.pickle'
### Check if token dir exists first, if not, create the folder
if not os.path.exists(os.path.join(working_dir, token_dir)):
os.mkdir(os.path.join(working_dir, token_dir))
if os.path.exists(os.path.join(working_dir, token_dir, pickle_file)):
with open(os.path.join(working_dir, token_dir, pickle_file), 'rb') as token:
cred = pickle.load(token)
if not cred or not cred.valid:
if cred and cred.expired and cred.refresh_token:
cred.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(CLIENT_SECRET_FILE, SCOPES)
cred = flow.run_local_server()
with open(os.path.join(working_dir, token_dir, pickle_file), 'wb') as token:
pickle.dump(cred, token)
try:
service = build(API_SERVICE_NAME, API_VERSION, credentials=cred)
print(API_SERVICE_NAME, API_VERSION, 'service created successfully')
return service
except Exception as e:
print(e)
print(f'Failed to create service instance for {API_SERVICE_NAME}')
os.remove(os.path.join(working_dir, token_dir, pickle_file))
return None
And I create the service object using:
created_event = service.events().quickAdd(
calendarId=Calendar_two,
text=eventtext).execute()
When ran as a .py it works fine and I get the "serivce created successfully" print, but when ran as exe it fails and gives me the "failed to create service" print and spits out the following error: "AttributeError: 'NoneType' object has no attribute 'events".
Visual studio PyLint also spits out this error: Instance of 'Resource' has no 'events' member [E:no-member]. But again, it still works as a .py
Here is the same code in a google example
This guy had the exact same problem a few months ago but didn't get any replies
I have an excel file in my local computer that I would like to upload into google drive using python via an API.
The following is my code:
import pickle
import os
from google_auth_oauthlib.flow import Flow, InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.http import MediaFileUpload, MediaIoBaseDownload
from google.auth.transport.requests import Request
from googleapiclient.http import MediaFileUpload
def Create_Service(client_secret_file, api_name, api_version, *scopes):
print(client_secret_file, api_name, api_version, scopes, sep='-')
CLIENT_SECRET_FILE = client_secret_file
API_SERVICE_NAME = api_name
API_VERSION = api_version
SCOPES = [scope for scope in scopes[0]]
print(SCOPES)
cred = None
pickle_file = f'token_{API_SERVICE_NAME}_{API_VERSION}.pickle'
if os.path.exists(pickle_file):
with open(pickle_file, 'rb') as token:
cred = pickle.load(token)
if not cred or not cred.valid:
if cred and cred.expired and cred.refresh_token:
cred.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(CLIENT_SECRET_FILE, SCOPES)
cred = flow.run_local_server()
with open(pickle_file, 'wb') as token:
pickle.dump(cred, token)
try:
service = build(API_SERVICE_NAME, API_VERSION, credentials=cred)
print(API_SERVICE_NAME, 'service created successfully')
return service
except Exception as e:
print('Unable to connect.')
print(e)
return None
def convert_to_RFC_datetime(year=1900, month=1, day=1, hour=0, minute=0):
dt = datetime.datetime(year, month, day, hour, minute, 0).isoformat() + 'Z'
return dt
CLIENT_SECRET_FILE = '/Users/shruthiravishankar/Downloads/client_secret_316665721335-819139d5ea0aeet1ddshhk6p0mpl8mv2.apps.googleusercontent.com.json'
API_NAME = 'Desktop client 1'
API_VERSION = 'v3'
SCOPES =['https://www.googleapis.com/auth/drive']
service = Create_Service(CLIENT_SECRET_FILE,API_NAME, API_VERSION, SCOPES)
folder_id='10Xct2T1vBpqW3-3Ud6mjPuf_lKCN1bUL'
file_names = ['Manual_SIC_MVP (9).xlsx']
mime_types = ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']
for file_name, mime_type in zip(file_names, mime_types):
file_metadata = {
'name': file_name,
'parents': [folder_id]
}
media = MediaFileUpload('/Users/shruthiravishankar/Downloads/{0}'.format(file_name), mimetype=mime_type)
print(media)
service.files().create(
supportsTeamDrives=True,
body=file_metadata,
media_body=media,
fields='id'
).execute()
The error that I am getting is:
Unable to connect and none files.
Is there an issue with he api_version and scope? Unable to figure out the issue. This is my first time dealing with api.
The issue is with this statement actually:
API_NAME = 'Desktop client 1'
That's not a valid Google service name.
This particular library needs to know which API service it needs to build, not how you want to call it.
Change that line to the following:
API_NAME = 'drive'
See the github line in question here and the general quickstart docs here
I have tried almost everything on google documentation and almost all the possibilities I could explore by myself. I still cant file a viable solution.
I just need to create a program which uploads a given file for example "test.zip" in my working directory to google drive.
I have a client_secret.json but none of the solutions actually help online as I am having issues with authentication.
from Google import Create_Service
from googleapiclient.http import MediaFileUpload
CLIENT_SECRET_FILE = "client_secret.json"
API_NAME = "drive"
API_VERSION = "v3"
SCOPES = ["https://www.googleapis.com/auth/drive"]
service = Create_Service(CLIENT_SECRET_FILE,API_NAME,API_VERSION,SCOPES)
folder_id = "1QpsQB_R7JyqxueQwIe8_AvKGm7a25IoJ"
file_names = ["my_file.zip"]
mime_types = ['application/zip']
for file_name , mime_type in zip(file_names , mime_types):
file_metadata = {
"name" : file_name,
"parents" : [folder_id]
}
media = MediaFileUpload('./Uploads/{0}'.format(file_name), mimetype=mime_type)
service.files().create(
body = file_metadata,
media_body = media,
fields = "id"
).execute()
this is the code I am using right now,
Create_service is being taken from google.py
import pickle
import os
from google_auth_oauthlib.flow import Flow, InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.http import MediaFileUpload, MediaIoBaseDownload
from google.auth.transport.requests import Request
def Create_Service(client_secret_file, api_name, api_version, *scopes):
print(client_secret_file, api_name, api_version, scopes, sep='-')
CLIENT_SECRET_FILE = client_secret_file
API_SERVICE_NAME = api_name
API_VERSION = api_version
SCOPES = [scope for scope in scopes[0]]
print(SCOPES)
cred = None
pickle_file = f'token_{API_SERVICE_NAME}_{API_VERSION}.pickle'
# print(pickle_file)
if os.path.exists(pickle_file):
with open(pickle_file, 'rb') as token:
cred = pickle.load(token)
if not cred or not cred.valid:
if cred and cred.expired and cred.refresh_token:
cred.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(CLIENT_SECRET_FILE, SCOPES)
cred = flow.run_local_server()
with open(pickle_file, 'wb') as token:
pickle.dump(cred, token)
try:
service = build(API_SERVICE_NAME, API_VERSION, credentials=cred)
print(API_SERVICE_NAME, 'service created successfully')
return service
except Exception as e:
print('Unable to connect.')
print(e)
return None
def convert_to_RFC_datetime(year=1900, month=1, day=1, hour=0, minute=0):
dt = datetime.datetime(year, month, day, hour, minute, 0).isoformat() + 'Z'
return dt
but even after allowing authentication it shows,
any help will be appreciation :)
When I run my code, I am able to login, but as soon as I try to authenticate, the server crashes and I'm assuming that's because I am not getting any access tokens. I am not sure on where to go next. I have downloaded the .json file for my credentials and its called 'credentials.json'
This is my Google.py
import pickle
import os
import datetime
from google_auth_oauthlib.flow import Flow, InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.http import MediaFileUpload, MediaIoBaseDownload
from google.auth.transport.requests import Request
def Create_Service(client_secret_file, api_name, api_version, *scopes, prefix=''):
CLIENT_SECRET_FILE = client_secret_file
API_SERVICE_NAME = api_name
API_VERSION = api_version
SCOPES = [scope for scope in scopes[0]]
cred = None
working_dir = os.getcwd()
token_dir = 'token files'
pickle_file = f'token_{API_SERVICE_NAME}_{API_VERSION}{prefix}.pickle'
### Check if token dir exists first, if not, create the folder
if not os.path.exists(os.path.join(working_dir, token_dir)):
os.mkdir(os.path.join(working_dir, token_dir))
if os.path.exists(os.path.join(working_dir, token_dir, pickle_file)):
with open(os.path.join(working_dir, token_dir, pickle_file), 'rb') as token:
cred = pickle.load(token)
if not cred or not cred.valid:
if cred and cred.expired and cred.refresh_token:
cred.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(CLIENT_SECRET_FILE, SCOPES)
cred = flow.run_local_server()
with open(os.path.join(working_dir, token_dir, pickle_file), 'wb') as token:
pickle.dump(cred, token)
try:
service = build(API_SERVICE_NAME, API_VERSION, credentials=cred)
print(API_SERVICE_NAME, API_VERSION, 'service created successfully')
return service
except Exception as e:
print(e)
print(f'Failed to create service instance for {API_SERVICE_NAME}')
os.remove(os.path.join(working_dir, token_dir, pickle_file))
return None
def convert_to_RFC_datetime(year=1900, month=1, day=1, hour=0, minute=0):
dt = datetime.datetime(year, month, day, hour, minute, 0).isoformat() + 'Z'
return dt
if __name__ == '__main__':
API_NAME = 'calendar'
API_VERSION = 'v3'
SCOPES = ['https://www.googleapis.com/auth/calendar']
CLIENT_FILE = 'client-secret.json'
service = Create_Service(CLIENT_FILE, API_NAME, API_VERSION, SCOPES, 'x')
This is my code to run
from pprint import pprint
from Google import Create_Service
CLIENT_SECRET_FILE = 'credentials.json'
API_NAME = 'calendar'
API_VERSION = "v3"
SCOPES = ['https://www.googleapis.com/auth/calendar']
service = Create_Service(CLIENT_SECRET_FILE, API_NAME, API_VERSION, SCOPES)
The Google Sheets API Python Quickstart currently uses deprecated packages in its example code, where the use of oauth2client and httplib2 rather than google-auth and google-auth-oauthlib (or maybe google-auth?) is outdated or soon to be.
How do I rewrite this code to use these new libraries in a way that best anticipates their current state and the eventual move to google-auth, etc.? In particular, is there a simple reimplementation of retrieval, storage, and use of credentials in the quickstart (below) that brings it up to date?
from __future__ import print_function
import httplib2
import os
from apiclient import discovery
from oauth2client import client
from oauth2client import tools
from oauth2client.file import Storage
try:
import argparse
flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
except ImportError:
flags = None
SCOPES = 'https://www.googleapis.com/auth/spreadsheets.readonly'
CLIENT_SECRET_FILE = 'client_secret.json'
APPLICATION_NAME = 'Google Sheets API Python Quickstart'
def get_credentials():
home_dir = os.path.expanduser('~')
credential_dir = os.path.join(home_dir, '.credentials')
if not os.path.exists(credential_dir):
os.makedirs(credential_dir)
credential_path = os.path.join(credential_dir, 'sheets.googleapis.com-python-quickstart.json')
store = Storage(credential_path)
credentials = store.get()
if not credentials or credentials.invalid:
flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
flow.user_agent = APPLICATION_NAME
if flags:
credentials = tools.run_flow(flow, store, flags)
else: # Needed only for compatibility with Python 2.6
credentials = tools.run(flow, store)
print('Storing credentials to ' + credential_path)
return credentials
def main():
credentials = get_credentials()
http = credentials.authorize(httplib2.Http())
discoveryUrl = 'https://sheets.googleapis.com/$discovery/rest?version=v4'
service = discovery.build('sheets', 'v4', http=http, discoveryServiceUrl=discoveryUrl)
# etc. ...
How about this answer? I prepared the sample script for the Quickstart of Sheets API.
In this sample, it supposes below.
Sheet API is enabled
You have a client_secret.json.
In this sample, at first, refresh token is retrieved using authorization code. The refresh token is saved to sheets.googleapis.com-python-quickstart.json. After 1st run, the access token is retrieved by the refresh token.
In this sample, cell values are retrieved from spreadsheet.
Sample script :
import copy
import json
import os
import pprint
import google.oauth2.credentials
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
pp = pprint.PrettyPrinter(indent=2)
CLIENT_SECRETS_FILE = "client_secret.json"
SCOPES = ['https://www.googleapis.com/auth/spreadsheets.readonly']
API_SERVICE_NAME = 'sheets'
API_VERSION = 'v4'
def get_authenticated_service():
credential_path = os.path.join("./", 'sheets.googleapis.com-python-quickstart.json')
if os.path.exists(credential_path):
with open(credential_path, 'r') as f:
credential_params = json.load(f)
credentials = google.oauth2.credentials.Credentials(
credential_params["access_token"],
refresh_token=credential_params["refresh_token"],
token_uri=credential_params["token_uri"],
client_id=credential_params["client_id"],
client_secret=credential_params["client_secret"]
)
else:
flow = InstalledAppFlow.from_client_secrets_file(CLIENT_SECRETS_FILE, SCOPES)
credentials = flow.run_console()
with open(credential_path, 'w') as f:
p = copy.deepcopy(vars(credentials))
del p["expiry"]
json.dump(p, f, indent=4)
return build(API_SERVICE_NAME, API_VERSION, credentials=credentials)
def spreadsheets_get(service):
spreadsheetId = "### spreadsheet ID ###"
rangeName = "Sheet1!a1:a10"
results = service.spreadsheets().get(
spreadsheetId=spreadsheetId,
ranges=rangeName
).execute()
pp.pprint(results)
if __name__ == '__main__':
os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'
service = get_authenticated_service()
spreadsheets_get(service)
Note :
In order to save credentials, it was required to use oauth2client.file. So I prepared the sample script without using oauth2client.file. If you want to use oauth2client.file, please modify it.
I think that Quickstart for Sheets API may be also updated in the near future.
References :
References I refered to prepare this sample script are as follows.
Using OAuth 2.0 for Installed Applications
There is a sample script for python.
User Guide
google.oauth2.credentials module
Using OAuth 2.0 for Web Server Applications
If I misunderstand your question, I'm sorry.