nithinmurali / pygsheets

Google Sheets Python API v4
https://pygsheets.readthedocs.io/en/latest
Other
1.51k stars 220 forks source link

using pyinstaller when importing pygsheets #490

Closed danagold404 closed 3 years ago

danagold404 commented 3 years ago

Hi everyone! I'm trying to create an exe file to distribute among users in my company. the exe file open a simple GUI (made with Tkinter), which allows the user to select a txt file from their pc and inserts the data from the txt into a Google sheet. I tested my python script before attempting to turn it into an exe and it worked great. but now, when I'm trying to use Pyinstaller it shows the following error:

C:\Users\Asus\PycharmProjects\dmtrial\venv\dist>DMPulse2GS.exe
Traceback (most recent call last):
  File "pygsheets\sheet.py", line 39, in __init__
FileNotFoundError: [Errno 2] No such file or directory: 'C:\\Users\\Asus\\AppData\\Local\\Temp\\_MEI102362\\pygsheets\\data\\sheets_discovery.json'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "DMPulse2GS.py", line 39, in <module>
  File "pygsheets\authorization.py", line 131, in authorize
  File "pygsheets\client.py", line 61, in __init__
  File "pygsheets\sheet.py", line 42, in __init__
  File "googleapiclient\_helpers.py", line 134, in positional_wrapper
  File "googleapiclient\discovery.py", line 291, in build
  File "googleapiclient\discovery.py", line 405, in _retrieve_discovery_doc
googleapiclient.errors.UnknownApiNameOrVersion: name: sheets  version: v4
[11284] Failed to execute script DMPulse2GS

this is the cmd command I used to create the exe file: C:\Users\Asus\PycharmProjects\dmtrial\venv>pyinstaller --onefile DMPulse2GS.py

it created three folders in this directory called: 'dist', 'build', and 'pycache'

after it finished running successfully, I copied my Service Accounts Key (json file) to the 'dist' folder created by Pyinstaller. (I also tried adding the file using --add-data when running pyinstaller for the first time on the file but it returns the same error)

then I tried clicking the exe file, which was when it returned the above error.

I tried everything!! any help / tips would be amazing! Thanks in advance!

mjstamper commented 3 years ago

I am receiving the same error converting my script to an EXE via pyinstaller. This is only when I run the .exe file. The python file runs with no issues.

Traceback (most recent call last):
  File "pygsheets\sheet.py", line 39, in __init__
FileNotFoundError: [Errno 2] No such file or directory: 'C:\\Users\\<redacted>\\AppData\\Local\\Temp\\_MEI104322\\pygsheets\\data\\sheets_discovery.json'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "cli.py", line 4, in <module>
    main()
  File "rps_nba\__main__.py", line 272, in main
    client = pygsheets.authorize(service_file = key_file)
  File "pygsheets\authorization.py", line 131, in authorize
  File "pygsheets\client.py", line 61, in __init__
  File "pygsheets\sheet.py", line 42, in __init__
  File "googleapiclient\_helpers.py", line 134, in positional_wrapper
  File "googleapiclient\discovery.py", line 291, in build
  File "googleapiclient\discovery.py", line 405, in _retrieve_discovery_doc
googleapiclient.errors.UnknownApiNameOrVersion: name: sheets  version: v4
[28348] Failed to execute script cli
mjstamper commented 3 years ago

I made a breakthrough with some testing. When I used pyinstaller without the --onefile option, I found the library for pygsheets was missing in the distfolder. I copied my pygsheets folder from the AppData\Local\Programs\Python\Python38\Lib\site-packages folder. This cleared the error and my EXE was able to run.

I hope this helps as a work-a-round.

satya0826 commented 3 years ago

The issue here is with this code self.service = discovery.build('sheets', 'v4', http=http) in sheet.py and drive.py. It needs one more argument discoveryServiceUrl in order to fetch the discover.json files online, if not available locally and it is available for the pyinstaller packed executable file. I did a quick fix in sheet.py by modifying

        try:
            with open(os.path.join(data_path, "sheets_discovery.json")) as jd:
                self.service = discovery.build_from_document(json.load(jd), http=http)
        except:
            self.service = discovery.build('sheets', 'v4', http=http)

into this:

       try:
            with open(os.path.join(data_path, "sheets_discovery.json")) as jd:
                self.service = discovery.build_from_document(json.load(jd), http=http)
        except:
            DISCOVERY_SERVICE_URL = 'https://sheets.googleapis.com/$discovery/rest?version=v4'
            self.service = discovery.build('sheets', 'v4', http=http, discoveryServiceUrl=DISCOVERY_SERVICE_URL)

Similarly in drive.py:

       try:
            with open(os.path.join(data_path, "drive_discovery.json")) as jd:
                self.service = discovery.build_from_document(json.load(jd), http=http)
        except:
            DISCOVERY_SERVICE_URL = 'https://www.googleapis.com/discovery/v1/apis/drive/v3/rest'
            self.service = discovery.build('drive', 'v3', http=http, discoveryServiceUrl=DISCOVERY_SERVICE_URL)

I got the URLs from the website https://developers.google.com/discovery/v1/reference/apis/list searching in the API Explorer. Also, it seems the URLs can be constructed by using the api name and version. Check the code here Code Snippet from that link:

 # Build a service object for interacting with the API.
  api_root = 'https://guestbook.appspot.com/_ah/api'
  api = 'guestbook'
  version = 'v0.2'
  discovery_url = '%s/discovery/v1/apis/%s/%s/rest' % (api_root, api, version)
  service = build(api, version, discoveryServiceUrl=discovery_url)
danagold404 commented 3 years ago

I tried @mjstamper tip and it worked! but it's not a good enough solution for me because I need to be able to make my app into one file and to send to the analysts that will be working on it, and not a whole folder. I noticed the issue @satya0826 mentioned, but because I'm quite new to GitHub I didn't know how to implement the changes and use them on my computer - i.e. how can I take the changes you made in the package and use them on my computer instead of the pygsheets package I currently have set up? Thanks again for all the help guys!

nithinmurali commented 3 years ago

@satya0826 Thanks, I will apply the fix. @danagold404 you can install from github once the fix is in github. Or you can clone and make the change locally and install pygsheets from that source.

nithinmurali commented 3 years ago

@satya0826 was this issue solved by adding service URL? did you test it? because according to the source of build method. the discoveryServiceUrl has a default value which points to the google api.

nithinmurali commented 3 years ago

@danagold404 hardcoded the URI, please verify if this fixes the issue.

Awais-Bin-Riaz commented 3 years ago

I made a breakthrough with some testing. When I used pyinstaller without the --onefile option, I found the library for pygsheets was missing in the distfolder. I copied my pygsheets folder from the AppData\Local\Programs\Python\Python38\Lib\site-packages folder. This cleared the error and my EXE was able to run.

I hope this helps as a work-a-round.

please provide full description, which file or folder you copy and where you paste in which folder you paste it.

Awais-Bin-Riaz commented 3 years ago

@mjstamper please provide full description of it

mjstamper commented 3 years ago

@Awais-Bin-Riaz I am not sure what more you need. The folder is the local install of pygheets and placed in the dist folder, created by pyinstaller.

I hope this helps.

nithinmurali commented 3 years ago

A fix for this is deployed in staging. Please install from there. ref #493

pip install -U https://github.com/nithinmurali/pygsheets/archive/staging.zip

renatovoss commented 2 years ago

@mjstamper answer saved me. Copy and paste the libraries worked. Just a little thing was different: i didnt find the library in AppData\Local\Programs\Python\Python38\Lib\site-packages, i found it in C:\Users\_my_user_\anaconda3\Lib\site-packages, but still, it gave me the way.

CaioSilva88 commented 2 years ago

I had the same issue as well, and I tried to fix by copy and paste the libraries and modifying sheet.py and drive.py like @satya0826 did. Does anyone has a suggestion? Here is my error Traceback (most recent call last): File "loop.py", line 248, in File "googleapiclient_helpers.py", line 130, in positional_wrapper File "googleapiclient\discovery.py", line 287, in build File "googleapiclient\discovery.py", line 404, in _retrieve_discovery_doc googleapiclient.errors.UnknownApiNameOrVersion: name: sheets version: v4

dinhitcom commented 2 years ago

I had the same issue as well, and I tried to fix by copy and paste the libraries and modifying sheet.py and drive.py like @satya0826 did. Does anyone has a suggestion? Here is my error Traceback (most recent call last): File "loop.py", line 248, in File "googleapiclient_helpers.py", line 130, in positional_wrapper File "googleapiclient\discovery.py", line 287, in build File "googleapiclient\discovery.py", line 404, in _retrieve_discovery_doc googleapiclient.errors.UnknownApiNameOrVersion: name: sheets version: v4

I did the same and still got the issue. Fixed it by using --collect-data pygsheets flag to pyinstaller cmd