0

非圧縮の .tar ファイルに変換したい圧縮された .zip ファイルがあります。

私はそれを行うためにこの関数を作りました:

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"

実行中に次のエラーが発生します。

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'

https://stackoverflow.com/a/2656405/2518263から取得した onError は次のとおりです。

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

ランダムな場合にのみエラーが発生します。解凍機能は 75% の確率で機能します。

なぜこのエラーが発生するのかわかりません。誰かがこれを行うためのより良い方法またはこのエラーを解決する方法を提案できますか.


私はちょうど置き換えました:

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

と:

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)

今では魅力のように機能します。

編集:気にしないでください!私はまだエラーが発生しますが、頻度は低くなり、現在は約 20% の確率です!! 助けてください!

編集2:

OK、一時ファイルに抽出してもエラーは発生しないので、次のコードを使用しています。

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"

私は今働いています!(エラーが再発しないことを願っています)

編集 3: 再びエラーが発生しました!!!!!!!!!! これは本当に私の神経質になっています。誰か助けてください。

4

1 に答える 1

1

OS の一部のプロセスが、削除中のディレクトリに別のファイルを作成しようとしているようです。

一時ファイルの作成を避け、元の ZIP の解凍部分を新しい TAR ファイルに直接フィードすることをお勧めします。

これには、ZipInfo フィールドを TarInfo フィールドと一致させる必要がありますが、簡単なはずです。

これが私の見解です:

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()
于 2013-08-25T19:44:57.203 に答える