I'm using PyInstaller on Windows to make an .exe file of my project, basically my projects generates a csv file as output and the name of the csv file is dependent on the current time so the program generates unique file each time it is ran
I couldn't find any resource online that could help me with this problem
PyInstaller Command that I used: (data.csv file added is supposed to be bundled with exe so no issue there)
pyinstaller src\main.py -F --name "Attendance_System" --add-data "src\data.csv;data" --add-data "C:\Users\Darshit Shah\OneDrive\Desktop\TCET\Att_Sys\att_sys\Lib\site-packages\customtkinter;customtkinter" --clean
code block where the file is generated:
except KeyboardInterrupt:
timer.cancel()
endTime = str(dt.datetime.now().time())
op_file = f"{app.currdate}_{app.startTime[0:-7]}_{endTime[0:-7]}.csv".replace(":","-")
app.getList().to_csv(f"{op_file}")
print("O/P File generated")
sys.exit()
Basically the code generates the file in the folder where my main.py is located but after bundling it with PyInstaller i cant seem to achieve that
my_proj
|
|--build
|
|--dist <--- "This is Where i want my output file to generate"
| `--my_proj.exe
|
|--proj_venv
| |--Include
| |--Lib
| |--Scripts
| `--pyvenv.cfg
|
`--src <--- "Folder where my output file would normally generate without .exe"
|--classes.py
|--interface.py
|--main.py
`--data.csv
I echo @mrblue6's statement, but through past coding, believe that the line
app.getList().to_csv(f"{op_file}")
is the problem here. This would appear to generate the file in (most probably) the %TEMP%\_MEIXXXX
folder (under the local AppData folder). This is because a compiled program uses a subdirectory of %TEMP%
as its working directory (on Windows at least)
After posting, I remembered that as long as the output csv is in the same folder as your exe, you could do something like the following:
op_path = os.path.join(os.path.dirname(sys.executable), op_file)
As sys.executable
holds the full path to the exe when compiled. This seems like a more robust solution than what I previously suggested. This would make:
import os
import sys # if you haven't already
op_file = f"{app.currdate}_{app.startTime[0:-7]}_{endTime[0:-7]}.csv".replace(":","-")
op_path = os.path.join(os.path.dirname(sys.executable), op_file)
app.getList().to_csv(f"{op_path}")
print("O/P File generated")
I would try to change the name output to have an absolute path instead of just a file name, something like:
app.getList().to_csv(f"C:\users\dcs_2002\path\to\my_proj\dist\{op_file}")
for basic usage. If you want this is work elsewhere, it depends on the actual location of your my_proj
folder, but I would do something like the following (assuming my_proj
is in your home directory:
op_path = os.path.expanduser(f"~\\path\\to\\my_proj\\dist\\{op_file}")
# OR
op_path = os.path.join(os.path.expanduser("~"), "path", "to", "my_proj", "dist", op_file)
Both of these would work as os.path.expanduser()
expands any leading ~
's to the path of your home directory. You could also use os.path.expandvars()
to expand more complex percent-enclosed variables (ie `os.path.expandvars("%LOCALAPPDATA%\rest\of\path"). Obviously modify the paths to suit your needs, just make sure to replace any backslashes with a double backslash (to escape Python). All together this would be:
import os # if you haven't already
op_file = f"{app.currdate}_{app.startTime[0:-7]}_{endTime[0:-7]}.csv".replace(":","-")
op_path = os.path.expanduser(f"~\\path\\to\\my_proj\\dist\\{op_file}")
app.getList().to_csv(f"{op_path}")
print("O/P File generated")