2

I'm very new to Python programming and I've cobbled together some code that will hopefully automatically rename a bunch files in a specific folder. I need to run this program on a computer without Python installed (it's not connected to the internet and I can't install python on it) so I've converted the .py file to a .exe file using auto-py-to-exe. The .py file works on my laptop, so the problem only shows up when I try to run the .exe file.

I use the path to the folder that the script is located in throughout the code so at the beginning of the script, I save the filepath as "path":

path = os.path.dirname(os.path.realpath(__file__))

However, when I convert the .py file to a .exe file and move that .exe file to another folder, the filepath that is saved in the 'path' variable is in a temp folder (probably the output location of the file converter). I tested it by isolating the part of the script that gets the filepath and making a .exe file to print just that filepath.

Is there a different way that I can get the filepath of the executable file? I don't want to hardcode the filepath into the program because people constantly reorganize the folders on that computer and I want this program to be flexible.

Here is the rest of the code if it's needed for context. Thank you and I'm sorry if this is a really basic question :)

#  This section of code imports the modules used below
import os
import tkinter as tk
from tkinter import simpledialog
from tkinter import messagebox

#  Setting global variables
path = os.path.dirname(os.path.realpath(__file__)) + "/"  # This sets the filepath to the current folder

#  Choosing the dough
dough_input = tk.Tk(className='Select dough')
dough_input.geometry('400x200')

# This is the code that creates the dough selection box. Any new types can be added here using the template below:
dough = tk.StringVar()
radiobutton_1 = tk.Radiobutton(dough_input, text='a', variable=dough, value="a", tristatevalue=0)
radiobutton_1.pack()
radiobutton_2 = tk.Radiobutton(dough_input, text='b', variable=dough, value="b", tristatevalue=0)
radiobutton_2.pack()
radiobutton_3 = tk.Radiobutton(dough_input, text='c', variable=dough, value="c", tristatevalue=0)
radiobutton_3.pack()
radiobutton_4 = tk.Radiobutton(dough_input, text='d', variable=dough, value="d", tristatevalue=0)
radiobutton_4.pack()


# This section of code saves the dough chosen and closes the pop-up window.
def submitfunction():
    global bread
    bread = dough.get()
    dough_input.destroy()


submit = tk.Button(dough_input, text='Submit', command=submitfunction)
submit.pack()

# This section of code triggers the pop-up window for the dough selection.
dough_input.mainloop()

#  Inputting the first number
root = tk.Tk()
root.withdraw()
user_inp = simpledialog.askinteger("Number Input", "Input first number:")
i = int(user_inp)

#  Defining the file rename function
def rename():
    global i  # use the variable  "i" defined above (The number that the user inputs)
    for filename in os.listdir(path):  # for each file in the folder specified above do the following
        if ".sur" in filename:
            my_dest = str(bread) + " " + str(i).zfill(4) + ".txt"  # sets the new filename
            my_source = path + filename  # Defines the old filepath to the file
            my_dest = path + my_dest  # Defines the new filepath to the file
            os.rename(my_source, my_dest)  # rename function
            i = i + 1  # advances the program down the list
    messagebox.showinfo("Success", "All files have been renamed successfully!")  # confirmation message!


# This function asks the user if the information they've input is correct. Once the user clicks "ok" the program runs
# the rename function.
def sanity_check():
    file_list = os.listdir(path)
    j = 0
    for g in file_list:
        if ".txt" in g:
            j += 1

    # This section of code does some calculations and creates a "sanity check" for the user. It takes the number that
    # the user inputted above and sets that as the first number "i". Then it counts the number of files that
    # meets the above criteria and sets that to the number of files. It uses that number of files to calculate the
    # last number in the list. It then concatenates all this information and asks the user to 
    # confirm. If the user presses "ok" then the program
    # proceeds with the rename. If the user presses cancel, the program aborts.

    first_num = i
    num_files = j
    length_files = int(num_files) - 1
    last_file = i + length_files
    last_num = last_file
    check = str(
        "There are " + str(num_files) + " files in this folder. The dough analyzed is " + str(
            dough) + ". The first "
                       "number is " + str(first_num).zfill(
            4) + " and the last number is " + str(
            last_num).zfill(4) + ". Is this correct?")

    # This is the section of code that asks the user to verify the numbers.
    confirmation = messagebox.askokcancel("Sanity Check!", check)
    if confirmation == False:
        messagebox.showerror("", "Program Cancelled")
    else:
        rename()


# This is the command that runs the program.
sanity_check()
4
  • What is your use case? The Python executable makers basically make a zip. When you run the exe, it unpacks the zip to a temp location, including the Python interpreter and all of the modules you need, and runs your script in that mini Python environment. Usually, __file__ is what you want; that's where everything got unzipped. What good would the exe path do you? Commented Jul 21, 2021 at 22:33
  • Perhaps its best to change where the default directory is. "where ever the user happened to download the exe" is one choice. But user home directory may be better. Since this is tkinter, it should be easy to have a path chooser. Commented Jul 21, 2021 at 22:35
  • @TimRoberts The code is meant to rename text files in a specific folder. I envisioned the .exe file to be in the same folder as the .txt files so it's easy for the users to find. I know that the os.rename module needs the filepath to work, so I thought the best way to do that would be to use the filepath of the .exe file (in theory it will be the same as the .txt files). Commented Jul 22, 2021 at 17:51
  • maybe you are looking for sys.argv[0] Commented Feb 14, 2024 at 11:12

2 Answers 2

2

I think, os.getcwd() and sys.executable is what you are looking for. With these 2 functions you will know the folder you'r script running in (from where you started it), and the path to a current python executable (which probably will be included in a .exe distribution, and unpacked to a tmp dir):

$> mkdir -p /tmp/x
$> cd /tmp/x
$> pwd
/tmp/x
$> which python
/usr/bin/python
$> python
Python 3.9.5 (default, May 24 2021, 12:50:35)
[GCC 11.1.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.getcwd()
'/tmp/x'
>>> import sys
>>> sys.executable
'/usr/bin/python'
>>> 
Sign up to request clarification or add additional context in comments.

2 Comments

I don't think that solves the problem. sys.executable is going to point to the Python executable in the temporary directory. I'm not sure there is a way to know the location of the .exe that started everything, but I'm also not sure that's useful information to have.
That's what I'm saying. But I'm quite sure this won't affect CWD, from where user started the process, and that's usually enough information to have...
0

This worked for me.

import sys, os
if getattr(sys, 'frozen', False):
        application_path = os.path.dirname(sys.executable)
elif __file__:
        application_path = os.path.dirname(__file__)

I also faced similar situation and figured out the above logic would work no matter if I am having the .exe file or .py to run in production or for just testing.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.