I used pyinstaller to bundle a program into one .exe file, which as you know makes a temporary _MEIPASS folder on execution.
The program itself has an input method for exit via sys.exit() which removes the _MEIPASS folder, but if the user closes the terminal via the window close button (X) the folder remains, and by the next execution another _MEIPASS folder will be created which will lead to a lot of MEIPASS folders after a while.
I want to know:
Is there any way to force the .exe file to create a specific folder with the same name each time it runs to avoid multiple folders?
Or just make the 'X' button to act like sys.exit() and remove the _MEIPASS folder.
My .spec file:
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='CookieVPN',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir='E:/CookieVPNtmp/',
console=True , icon='cookievpn.ico')
I also tried:
I found a somewhat solution which I'm not sure if it is failproof or not but works for my scenario.
Add this function to your code and call it as the first line of your program to find any _MEI folder in %tmp% (or anywhere the program's _MEI folder will be located) and delete them. (It excludes the MEI for the current run)
#Imports
import glob
import sys
import os
from shutil import rmtree
def CLEANMEIFOLDERS():
#Getting the current run _MEI path
try:
base_path = sys._MEIPASS
#I don't know if this part is crucial or not since it only works if you don't use
#--onefile in pyinstaller, which makes the use of this function unnecessary
except Exception:
base_path = os.path.abspath(".")
#Extracting the updir of current run path to search for _MEI folders for the previous runs,
#cave man style. Please update this part if you know a better way.
base_path = base_path.split("\\")
base_path.pop(-1)
temp_path = ""
for item in base_path:
temp_path = temp_path + item + "\\"
#Search the path for _MEI folders and delete them if they are not for the current run
mei_folders = [f for f in glob.glob(temp_path + "**/", recursive=False)]
for item in mei_folders:
if item.find('_MEI') != -1 and item != sys._MEIPASS + "\\":
rmtree(item)
The code works but I will appreciate any tweak to make the code lighter :)
The solution from Sadra is good, but I wanted to keep a few "new" folders just in case a users runs the tool with multiple instances. Thus it wouldn't help to remove everything except the current run.
So I came up with the idea to check the creation date of a folder and delete everything older than X seconds. Here's the code just in case somebody needs it:
from shutil import rmtree
import time, os
def deleteOldPyinstallerFolders(time_threshold = 3600): # Default setting: Remove after 1 hour, time_threshold in seconds
try:
base_path = sys._MEIPASS
except Exception:
return # Not being ran as OneFile Folder -> Return
temp_path = os.path.abspath(os.path.join(base_path, '..')) # Go to parent folder of MEIPASS
# Search all MEIPASS folders...
mei_folders = glob.glob(os.path.join(temp_path, '_MEI*'))
for item in mei_folders:
if (time.time()-os.path.getctime(item)) > time_threshold:
rmtree(item)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With