Question

I have a compressed .zip file that i want to convert to an uncompressed .tar file.

I made this function to do it:

def decompress(filepath):
  devname = re.search("_(.+?)_.+?\.zip", filepath).group(1)
  with zipfile.ZipFile(filepath, 'r') as zip:
    path = os.path.join(start_dir, "Downloads", devname, str(os.path.basename(filepath))[:-4])
    zip.extractall(path)
  with tarfile.open(path + ".tar", 'w') as tar:
    for object in os.listdir(path):
      tar.add(os.path.join(path, object), arcname=object)
  time.sleep(2)
  shutil.rmtree(path, ignore_errors=False, onerror=onError)
  time.sleep(0.5)
  os.remove(filepath)
  return path + ".tar"

I am getting this error when running it:

Traceback (most recent call last):
  File "File.py", line 195, in <module>
    main()
  File "File.py", line 184, in main
    dld = download()
  File "File.py", line 132, in download
    filename = decompress(os.path.join(start_dir, "Downloads", devname, filename
))
  File "File.py", line 103, in decompress
    shutil.rmtree(path, ignore_errors=False, onerror=onError)
  File "C:\Program Files (x86)\python27\lib\shutil.py", line 247, in rmtree
    rmtree(fullname, ignore_errors, onerror)
  File "C:\Program Files (x86)\python27\lib\shutil.py", line 247, in rmtree
    rmtree(fullname, ignore_errors, onerror)
  File "C:\Program Files (x86)\python27\lib\shutil.py", line 256, in rmtree
    onerror(os.rmdir, path, sys.exc_info())
  File "C:\Program Files (x86)\python27\lib\shutil.py", line 254, in rmtree
    os.rmdir(path)
WindowsError: [Error 145] The directory is not empty: 'C:\\Users\\Vaibhav\\Deskt
op\\Folder\\Downloads\\toro\\_toro_nightly_test\\system\\app'

Here is my onError that I got from https://stackoverflow.com/a/2656405/2518263:

def onError(func, path, exc_info):
    """
    Error handler for ``shutil.rmtree``.

    If the error is due to an access error (read only file)
    it attempts to add write permission and then retries.

    If the error is for another reason it re-raises the error.

    Usage : ``shutil.rmtree(path, onerror=onerror)``
    """
    if not os.access(path, os.W_OK):
        # Is the error an access error ?
        os.chmod(path, stat.S_IWUSR)
        func(path)
    else:
        raise

I only get the error on random occasions. The decompress function works 75% of the time.

I don't know why I'm getting this error. Can someone suggest a better way to do this or a way to solve this error.


I just replaced:

shutil.rmtree(path, ignore_errors=False, onerror=onError)

with:

for root, dirs, files in os.walk(path, topdown=False):
    for name in files:
        filename = os.path.join(root, name)
        os.chmod(filename, stat.S_IWUSR)
        os.remove(filename)
    for name in dirs:
        os.rmdir(os.path.join(root, name))
  time.sleep(0.5)
  os.rmdir(path)

Now it works like a charm.

EDIT: Never mind! I still get the error but just less often, now its about 20% of the time!! Please help!

EDIT 2:

OK, so I don't get the error if i extract to a temporary file so I am using this code:

import tempfile
def decompress(filepath):
  with zipfile.ZipFile(filepath) as zip:
    tmp = tempfile.mkdtemp(dir=os.getcwd())
    zip.extractall(tmp)
  with tarfile.open(filepath[:-4] + ".tar", 'w') as tar:
    for object in os.listdir(tmp):
      tar.add(os.path.join(tmp, object), arcname=object)
  time.sleep(1)
  shutil.rmtree(tmp)
  os.remove(filepath)
  return filepath[:-4] + ".tar"

I works now! (hopefully the error won't occur again)

EDIT 3: I got the error again!!!!!!!!!! this is really getting on my nerves. Please help someone.

Était-ce utile?

La solution

Looks like some process in your OS manages to create another file in the directory you are in process of deletion of.

I can suggest you to avoid creation of temporary files and feed decompressed parts of original ZIP directly into new TAR file.

This require matching ZipInfo fields to TarInfo ones but it should be straightforward.

Here's my take on it:

def zip2tar(zipname, tarname):
    zipf = zipfile.ZipFile(zipname, 'r')
    tarf = tarfile.TarFile(tarname, 'w')
    timeshift = int((datetime.datetime.now() -
                     datetime.datetime.utcnow()).total_seconds())
    for zipinfo in zipf.infolist():
        tarinfo = tarfile.TarInfo()
        tarinfo.name = zipinfo.filename
        tarinfo.size = zipinfo.file_size
        tarinfo.mtime = calendar.timegm(zipinfo.date_time) - timeshift
        if zipinfo.internal_attr & 1:
            tarinfo.mode = 0666
            tarinfo.type = tarfile.REGTYPE
        else:
            tarinfo.mode = 0777
            tarinfo.type = tarfile.DIRTYPE 
        infile = zipf.open(zipinfo.filename)
        tarf.addfile(tarinfo, infile)
    zipf.close()
    tarf.close()
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top