Hello, I recently wrote a program that crops all the images in a directory and then stacks then all together. Then I made a simple GUI for the program which allows the user to input the directories and values. The programs have been able to run fine, but when I go to convert it to a .exe file, it states that it failed to execute the script. I used the code:
pyinstaller -w -F -i "filepath.ico" program.py
The file generates, but opening the file results in the error above. Do I have to do something additional to my code because I added the extra GUI (was able to get .exe to work without the GUI). Should I put the GUI and program in the same file? Also, my program runs fine python, but when its converted to a .exe file, there is always a 10 second delay before it will appear. This happens no matter how large the program is. I think it is due to Windows Defender block at first site. But I followed all the steps to disable it to no avail.
from tkinter import * from tkinter import filedialog from tkinter import messagebox from PIL import Image from natsort import natsorted import glob import gc import RD_program # .py file containing the program code # --- functions --- def inputfile(): # opens prompt to select input folder master.inputdirectory = filedialog.askdirectory() print(master.inputdirectory) def outputfile(): # opens prompt to select save folder master.outputdirectory = filedialog.askdirectory() print(master.outputdirectory) def run(): # function to run entire program try: # if user input is incorrect, instead of stopping program, will output error coordinates = [int(x1input.get()), int(y1input.get()), int(x2input.get()), int(y2input.get())] image_count = int(countinput.get()) RD_program.process(master.inputdirectory, coordinates, image_count, master.outputdirectory) except Exception as ex: print('ex:', ex) messagebox.showwarning("Warning", "Wrong arguments:\n" + str(ex)) # --- main --- master = Tk() master.iconbitmap("One_Dimensional_Reaction_Diffusion_Program_Icon.ico") master.inputdirectory = None # default value at start master.outputdirectory = None # default value at start master.title("One Dimensional Reaction Diffusion Program") master.geometry("440x270") header1 = Label(master, text="One Dimensional Reaction Diffusion Program\n" "Created by: Alexander Tang\n") header1.grid(sticky="N", columnspan=8) instructions = Label(master, text="Type in the coordinates for the upper left (x1,y1) and bottom right (x2,y2) points:") instructions.grid(sticky="W", columnspan=8) x1 = Label(master, text="x1: ") x1.grid(sticky="E", column=0, row=2) x1input = Entry(master, width=5) x1input.grid(sticky="W", column=1, row=2) y1 = Label(master, text="y1: ") y1.grid(sticky="E", column=2, row=2) y1input = Entry(master, width=5) y1input.grid(sticky="W", column=3, row=2) x2 = Label(master, text="x2: ") x2.grid(sticky="E", column=4, row=2) x2input = Entry(master, width=5) x2input.grid(sticky="W", column=5, row=2) y2 = Label(master, text="y2: ") y2.grid(sticky="E", column=6, row=2) y2input = Entry(master, width=5) y2input.grid(sticky="W", column=7, row=2, pady=12) count = Label(master, text="How many images are being stacked? ") count.grid(sticky="W", column=0, row=4, columnspan=4) countinput = Entry(master, width=5) countinput.grid(stick="W", column=5, row=4, pady=3) step1 = Label(master, text="1. Select the file location: ") step1.grid(sticky="W", column=0, row=6, columnspan=4) step2 = Label(master, text="2. Select the save location: ") step2.grid(sticky="W", column=0, row=7, columnspan=4) btn_input = Button(master, text="Input Files", command=inputfile) # calls the function inputfile btn_input.grid(column=5, row=6, columnspan=2, pady=6) btn_output = Button(master, text="Output Location", command=outputfile) # calls the function outputfile btn_output.grid(column=5, row=7, columnspan=2) btn_run = Button(master, text="Run", font="Helvetica, 18", bg="blue", fg="white", command=run) # calls the function run btn_run.grid(sticky="S", column=5, row=8, columnspan=2, pady=6) mainloop()
from PIL import Image # for image processing from natsort import natsorted # sorting files import glob # access files import gc # deletes unneeded files import os # to be able to access directories def process(directory, coordinates, image_count, outputdirectory=None): # function assigning all variables x1, y1, x2, y2 = coordinates # Generate final image first # Width dependent on whether image is horizontal or vertical if (y2 - y1) > (x2 - x1): width = (y2 - y1) height = (x2 - x1) else: width = (x2 - x1) height = (y2 - y1) # Width is constant, total_height accounts for height above and the total number of images total_height = (image_count * height) new_im = Image.new('RGB', (width, total_height)) # Create a new colored image (RGB) # Keep outside of loop, if not, will reset y_offset each time # Indicates position of where to paste cropped image # Counter used to show progress of program y_offset = 0 counter = 0 # Accessing all the files using the glob module # The function natsorted sorts values the way Windows does # os.path.join(directory) opens prompt to choose folder # Opens all the files with the variable img in folder for filename in natsorted(glob.glob(os.path.join(directory, "*.*"), recursive=True)): img = Image.open(filename) # Cropping function selected_region = (x1, y1, x2, y2) # selected region from previous user input cropped_region = img.crop(selected_region) # taking opened image and cropping to selected region if (y2 - y1) > (x2 - x1): # If cropped area is vertical, rotate into horizontal position rotated_image = cropped_region.rotate(90, expand=1) # Expand 1 ensures image isn't cut off while rotating else: rotated_image = cropped_region # Does nothing if image is horizontal img.close() # Closes the initially opened image gc.collect() new_im.paste(rotated_image, (0, y_offset)) # (x,y) indicates which direction to offset in y_offset += rotated_image.size # y_offset (which had position 0) + the height of the image counter += 1 print(counter, " out of ", image_count, "completed.") # Shows progress of program if counter == image_count: # Will stop program when counter reaches number of images break final_im = new_im.rotate(180, expand=1) # stacking goes from top to bottom, rotate images at the end if outputdirectory is None: outputdirectory = directory final_im.save(os.path.join(outputdirectory, "stacked_image.tiff"), quality=95) def main(): # Convert coordinate list into variables print("Type in the coordinates for the upper left (x1,y1) and bottom right (x2,y2) points") coordinates = list(map(int, input("Separate values with a space (x1 y1 x2 y2): ").strip().split()))[:4] image_count = int(input("How many images are being stacked? ")) print("Generating image...") process(directory, coordinates, image_count) print("Image completed and can be found in the output folder.") input("Press ENTER to close program.") # prevents prompt from instantly closing if __name__ == " __main__": # allows you to run code without GUI main()