pythonshutil

Permission denied while overwriting python application


I made a crude auto-updating application using python, and made exe file using freeze-cx.

First, the app check whether a file of newest version is available on the firebase server, and download the zip file if available. And The app unzip and overwrite the files.

    this_file_path = sys.executable if getattr(sys, 'frozen', False) else __file__
    path_here = str(Path(this_file_path).parent.absolute())

    storagePath = '/version/File'+ver_recent+'.zip'
    storage.child(storagePath).download(path='', filename=path_here+'/File.zip')
    file_name = path_here+'/File.zip'
    output_dir = path_here+"\\"
    format = "zip"
    messagebox.showinfo('Update Ongoing', 'Downloading newest version is done. Extracting file to:'+output_dir)
    shutil.unpack_archive(file_name, output_dir, format)

Here, I intention is that my app overwrites all components in the folder.

I confirmed that if I tell my app to overwrite files in other folder, and I saw that other people say that this mechanism is possible.

Is it possible for a running python program to overwrite itself?

However, while running the program, it spits out the error message :

     open(targetpath, 'wb') as target:

PermissionError: [Errno13] Permission denied: C\\Users\\bboyc\\Documents\\File_0142\\lib\\_asyncio.pyd

Since I am still new with python, I cannot guess the exact reason. I just cannot understand why the file is refusing to be accessed.

Can anyone please tell me what is happenning or I am missing ? I succeeded overwriting when it was occured for not-running files, so I donot think its the matter of _asyncio.pyd file.


Solution

  • The problem was that I tried to replace a currently running file. I thought it could be done referring the link in my main writing but it seems it isn't.

    I solved the problem by producing a batch file that extracts the zip file in a temp folder and close the program, overwrite files, and re-run the program.

    How to write the batch file is like this :

    def create_update_script(temp_dir, program_dir, restart_script):
        update_script_path = Path(temp_dir) / "update.bat"
        with open(update_script_path, 'w') as file:
            file.write('@echo off\ntimeout /t 1 /nobreak > NUL\nxcopy /s /e /y "'+temp_dir+'\\*" "' +program_dir+'\\*"\ntimeout /t 1 /nobreak > NUL\nstart "" "'+str(restart_script)+'"\ndel "'+str(update_script_path)+'"')
        return update_script_path
    
    update_script_path = create_update_script(temp_dir, path_here, restart_script)
        subprocess.Popen(["cmd", "/c", str(update_script_path)])
    

    And everything worked.