I am trying to convert my.py file into a.exe file using PyInstaller. The process works out fine. However, when I try to run the.exe file, the program mentions that it can not locate "client_secret.json".
I am not sure how to include a JSON file correctly in the bundle of files, so I can execute my converted.exe file correctly.
I am quite new to PyInstaller, so please don't judge me too harsh:/
I have tried adding "client_secret.json" into the.spec file of PALSheet.spec, but the.exe file (updated) fails to run [also due to its failure to locate "client_secret.json"].
Here is the code of "PALSheet.py":
import tkinter
import gspread
from oauth2client.service_account import ServiceAccountCredentials
# use creds to create a client to interact with the Google Drive API and Google Sheets API
scope = 'https://spreadsheets.google.com/feeds','https://www.googleapis.com/auth/drive'
creds = ServiceAccountCredentials.from_json_keyfile_name('client_secret.json', scope)
client = gspread.authorize(creds)
# Find a workbook by name and open the first sheet
# Make sure you use the right name here.
sheet = client.open("PAL Tutoring Data SpreadSheet").sheet1
def ResetData():
student_entry.delete('0', 'end')
grade_entry.delete('0', 'end')
class_entry.delete('0', 'end')
topic_entry.delete('0', 'end')
def FindNextRow():
global next_row
next_row = ((len(sheet.col_values(int(1)))) + 1)
def InputData():
FindNextRow()
global next_row
sheet.update_cell(next_row, 1, student_entry.get())
sheet.update_cell(next_row, 2, grade_entry.get())
sheet.update_cell(next_row, 3, class_entry.get())
sheet.update_cell(next_row, 4, topic_entry.get())
student_entry.delete('0', 'end')
grade_entry.delete('0', 'end')
class_entry.delete('0', 'end')
topic_entry.delete('0', 'end')
window = tkinter.Tk()
window.title("PAL Data Input")
student_label = tkinter.Label(window, text = " Student Name: ")
student_label.grid(row = "2", column = "1")
student_entry = tkinter.Entry(window)
student_entry.grid(row = "2", column = "2")
grade_label = tkinter.Label(window, text = "Grade Level: ")
grade_label.grid(row = "3", column = "1")
grade_entry = tkinter.Entry(window)
grade_entry.grid(row = "3", column = "2")
class_label = tkinter.Label(window, text = "Math Class: ")
class_label.grid(row = "4", column = "1")
class_entry = tkinter.Entry(window)
class_entry.grid(row = "4", column = "2")
topic_label = tkinter.Label(window, text = " Problem Topic: ")
topic_label.grid(row = "5", column = "1")
topic_entry = tkinter.Entry(window)
topic_entry.grid(row = "5", column = "2")
process_button = tkinter.Button(window, text = "Update Sheet", command = InputData)
process_button.grid(row = "6", column = "2")
reset_button = tkinter.Button(window, text = "Reset Fields", command = ResetData)
reset_button.grid(row = "6", column = "1")
window.mainloop()
After I convert "PALSheet.py" to "PALSheet.exe", the file reads the following error:
Traceback (most recent call last): File "palsheet.py", line 9, in File "site-packages\oauth2client\service_account.py", line 219, in from_json_keyfile_name FileNotFoundError: [Errno 2] No such file or directory: 'client_secret.json' [280] Failed to execute script PALSheet
whenever you build a.exe with
pyinstaller -F foobar.py
pyinstaller will create a temporary directory in your appdata fodler containing the.exe's dependencies. If you build it without the -F flag, theese would be in the same directory as the executable itself. To access this temporary folder, you need to use a function like this:
import sys,os
def resource_path(relative_path: str) -> str:
""" Get absolute path to resource"""
try:
# PyInstaller creates a temp folder and stores path in _MEIPASS
base_path = sys._MEIPASS
except Exception:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
You can then replace "client_secret.json"
with ressource_path("client_secret.json")
and it will work even with pyinstaller's -F flag (and of cause without -F flag). You will need to append your data to the pyinstaller, so the new build command is:
pyinstaller -F --add-data "client_secret.json;client_secret.json" foobar.py
This is your new "PALSheet.py":
import tkinter
import gspread
from oauth2client.service_account import ServiceAccountCredentials
import sys,os
def resource_path(relative_path: str) -> str:
""" Get absolute path to resource"""
try:
# PyInstaller creates a temp folder and stores path in _MEIPASS
base_path = sys._MEIPASS
except Exception:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
# use creds to create a client to interact with the Google Drive API and Google Sheets API
scope = 'https://spreadsheets.google.com/feeds','https://www.googleapis.com/auth/drive'
creds = ServiceAccountCredentials.from_json_keyfile_name(ressource_path("client_secret.json"), scope)
client = gspread.authorize(creds)
# Find a workbook by name and open the first sheet
# Make sure you use the right name here.
sheet = client.open("PAL Tutoring Data SpreadSheet").sheet1
def ResetData():
student_entry.delete('0', 'end')
grade_entry.delete('0', 'end')
class_entry.delete('0', 'end')
topic_entry.delete('0', 'end')
def FindNextRow():
global next_row
next_row = ((len(sheet.col_values(int(1)))) + 1)
def InputData():
FindNextRow()
global next_row
sheet.update_cell(next_row, 1, student_entry.get())
sheet.update_cell(next_row, 2, grade_entry.get())
sheet.update_cell(next_row, 3, class_entry.get())
sheet.update_cell(next_row, 4, topic_entry.get())
student_entry.delete('0', 'end')
grade_entry.delete('0', 'end')
class_entry.delete('0', 'end')
topic_entry.delete('0', 'end')
window = tkinter.Tk()
window.title("PAL Data Input")
student_label = tkinter.Label(window, text = " Student Name: ")
student_label.grid(row = "2", column = "1")
student_entry = tkinter.Entry(window)
student_entry.grid(row = "2", column = "2")
grade_label = tkinter.Label(window, text = "Grade Level: ")
grade_label.grid(row = "3", column = "1")
grade_entry = tkinter.Entry(window)
grade_entry.grid(row = "3", column = "2")
class_label = tkinter.Label(window, text = "Math Class: ")
class_label.grid(row = "4", column = "1")
class_entry = tkinter.Entry(window)
class_entry.grid(row = "4", column = "2")
topic_label = tkinter.Label(window, text = " Problem Topic: ")
topic_label.grid(row = "5", column = "1")
topic_entry = tkinter.Entry(window)
topic_entry.grid(row = "5", column = "2")
process_button = tkinter.Button(window, text = "Update Sheet", command = InputData)
process_button.grid(row = "6", column = "2")
reset_button = tkinter.Button(window, text = "Reset Fields", command = ResetData)
reset_button.grid(row = "6", column = "1")
window.mainloop()
Now you need to run:
pyinstaller -F --add-data "client_secret.json;client_secret.json" "PALSheet.py"
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.