Python:在临时文件夹中处理_MEIPASS文件夹

时间:2019-07-29 20:49:36

标签: python pyinstaller

我使用pyinstaller将程序捆绑到一个.exe文件中,您知道该文件在执行时会创建一个临时的_MEIPASS文件夹。

程序本身具有通过sys.exit()退出的输入方法,该方法将删除_MEIPASS文件夹,但是如果用户通过窗口关闭按钮(X)关闭终端,则该文件夹将保留,并且在下次执行时将保留另一个_MEIPASS文件夹将被创建,一段时间后将导致很多MEIPASS文件夹。

我想知道:

  1. 是否有任何方法可以强制.exe文件每次运行时都以相同的名称创建一个特定的文件夹,以避免多个文件夹?

  2. 或者只需单击“ X”按钮以使其类似于sys.exit()并删除_MEIPASS文件夹。

我的.spec文件:

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')

我也尝试过:

  1. 'E:\ CookieVPNtmp \'
  2. 'E:// CookieVPNtmp //'
  3. 'E:\'
  4. '/ CookieVPNtmp' <---这将在执行程序的根目录中创建_MEIPASS文件夹

3 个答案:

答案 0 :(得分:3)

我找到了某种解决方案,我不确定它是否可以进行故障转移,但是可以解决我的情况。

将此功能添加到您的代码中,并将其作为程序的第一行,以在%tmp%(或程序的_MEI文件夹将位于的任何位置)中找到任何_MEI文件夹并将其删除。 (它不包括当前运行的MEI)

#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)

该代码有效,但是我希望通过任何改进使代码更轻:)

答案 1 :(得分:1)

首先,当您手动关闭窗口时,脚本将意外关闭(与按ctrl+c时不同),因此您将无法执行任何操作,因为操作系统会强制关闭它

但是您可以使用--runtime-tmpdir为文件创建一个固定文件夹,因此不会每次都生成该文件夹:

pyinstaller -F --runtime-tmpdir "Some/Path" test.py 

答案 2 :(得分:1)

Sadra的解决方案很好,但是我想保留一些“新”文件夹,以防万一用户使用多个实例运行该工具。因此,除去当前运行之外的所有内容都无济于事。

因此,我想到了检查文件夹的创建日期并删除所有X秒之前的内容的想法。这是代码,以防万一有人需要它:

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)
相关问题