python将压缩的zip转换为未压缩的tar

python将压缩的zip转换为未压缩的tar,python,zip,tar,shutil,Python,Zip,Tar,Shutil,我有一个压缩的.zip文件,我想转换成一个未压缩的.tar文件 我做这个函数就是为了做到这一点: 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.

我有一个压缩的.zip文件,我想转换成一个未压缩的.tar文件

我做这个函数就是为了做到这一点:

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'
我只在随机情况下得到错误。解压功能在75%的时间内工作

我不知道为什么会出现这个错误。有人能提出一个更好的方法来解决这个错误吗


我刚刚替换了:

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

现在它就像一个符咒

编辑: 不要介意!我仍然会出错,但只是很少出错,现在大约有20%的时间会出错!!请帮忙

编辑2:

好的,如果我提取到一个临时文件,那么我不会得到错误,所以我使用以下代码:

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:
我又犯了错误!!!!!!!!!!这真让我心烦。请帮助某人。

看起来操作系统中的某个进程设法在正在删除的目录中创建另一个文件

我可以建议您避免创建临时文件,并将原始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()

谢谢,你介意详细介绍一下zipinfo和tarinfo字段的匹配吗。或者为我提供一个链接?我添加了一些代码,可以准确地解释我的想法。非常感谢!它工作完美,比我的初始代码快得多!只是为了进一步测试,看看错误是否不会再次出现。:)只是一个简单的问题,当我尝试添加
os.remove(zipname)
时,我遇到了一个错误:
WindowsError:[error 32]进程无法访问该文件,因为它正被另一个进程使用:C:\\Users\\Vaibhav\\Desktop\\Folder\\Downloads\\devname\\zipname.zip
您是在
zipf.close()之后添加的吗?然后您可能会让其他进程打开此文件。可能是此脚本的某个旧实例。您可以尝试找出是谁用Process Explorer或Windows中现在使用的任何工具打开了它。
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"
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()