pythonautomationpython-zipfile

Python - WinError 32 when deleting last .zip file


I am trying to export .zip files from the Downloads folder into a directory for my work. Some file names repeat so I have set it up to rename files to be different as to not overlap. After it exports, I want it to delete the .zip files in Downloads but the very last .zip file for some reason throws a "[WinError 32] The process cannot access the file because it is being used by another process: {full file path}" I would appreciate some input on this!

import os, shutil, time
import zipfile

def unzip(download_path, dir_path):
    num = 0
    bad_files = 0
    to_delete = []
    for filename in os.listdir(download_path):
        f = os.path.join(download_path, filename)
        if (filename == "desktop.ini"):
            pass
        elif filename.endswith(".zip"):
            i = 0
            z = zipfile.ZipFile(download_path + '\\' + filename)
            print(z.namelist()) 
            with zipfile.ZipFile(f, 'r') as zObject:
                zObject.extractall(path=dir_path)
                    
            split_file = z.namelist()[0].split('/')[i]
            print(split_file)
            
            time.sleep(1)
            try:
                os.rename(dir_path + '\\' + split_file, f'{dir_path}\\{filename[:6]}.zip_{split_file}')
            except:
                os.rename(dir_path + '\\' + split_file, f'{dir_path}\\error_duplicate_{split_file}')
                pass

            to_delete.append(f)
            i += 1
            print(f"File {num + 1}")

        elif filename.endswith(".crdownload"):
            print("error: " + filename)
            bad_files += 1
            print(f"File {num + 1}")
        else:
            shutil.move(f'{download_path}\\{filename}', f'{dir_path}\\{filename}')
            print(f"File {num + 1}")
        num += 1
        time.sleep(2)

        for file in to_delete:
            os.remove(file)

    print(f"Bad files: {bad_files}")

The program runs great and does exactly what I want up until the last file when it throws the error. I have tried closing the .zip with zObject.close() but that does nothing, I am assuming because I am using the with clause. I have also tried a for loop

for _ in range(3):
         if not to_delete:
             break

         for file in to_delete.copy():
             try:
                 os.remove(file)
             except PermissionError:
                 pass
             else:
                 to_delete.remove(file)

with no luck...


Solution

  • The problem due to

    z = zipfile.ZipFile(download_path + '\\' + filename)
    

    This is never being closed. Each time through the loop you reuse the variable, so the garbage collector automatically closes the previous zip file. But the last one never gets closed.

    Use

    with zipfile.ZipFile(f) as z:
    

    around the section of the code that uses z so it gets closed automatically.