【问题标题】:Zipping a folder with os.walk使用 os.walk 压缩文件夹
【发布时间】:2016-10-17 08:33:47
【问题描述】:

我正在尝试使用 os.walk() 压缩一个文件夹以及每个包含的子文件夹和文件,但我无法删除根文件夹的文件夹路径 - 这意味着我想在打开 zip 文件时删除 D:\\Users\\Username\\Desktop ,而是直接打开到根文件夹。

我一直在尝试使用 os.path.basename() 和 zipfile 的 arcname 参数,但似乎无法正确使用:

def backupToZip(folder):

    import zipfile, os

    folder = os.path.abspath(folder) # make sure folder is absolute

    # Walk the entire folder tree and compress the files in each folder.  
    for foldername, subfolders, filenames in os.walk(folder):

        # Add the current folder to the ZIP file.
        backupZip.write(foldername)

        # Add all the files in this folder to the ZIP file.
        for filename in filenames:
            backupZip.write(os.path.join(foldername, filename))
    backupZip.close()

backupToZip('Sample Folder')

【问题讨论】:

  • 您能否发布您希望压缩存档结构的外观?您发布的代码有点令人困惑,因为它是递归的,没有对函数的初始调用。
  • @hobenkr:很抱歉有任何混淆 - 我希望 zip 文件夹结构为 Sample Folder\Subfolders and Files\Subfolders and Files 而不是 D:\\Users\\Username\\Desktop\\Sample Folder\\Subfolders and Files\\Subfolders and Files

标签: python zipfile


【解决方案1】:

根据上面user2313067的回答做了一些修改,终于得到了我想要的东西,以防有人好奇:

import zipfile, os

def backupToZip(folder):

    # Make sure folder is absolute.
    folder = os.path.abspath(folder) 

    backupZip = zipfile.ZipFile('backup.zip', 'w')

    backupZip.write(folder, arcname=os.path.basename(folder))


    # Walk the entire folder tree and compress the files in each folder.  
    for foldername, subfolders, filenames in os.walk(folder):

        # Add the current folder to the ZIP file if not root folder
        if foldername != folder:
            backupZip.write(foldername, arcname=os.path.relpath(foldername, os.path.dirname(folder)))

        # Add all the files in this folder to the ZIP file.
        for filename in filenames:
            backupZip.write(os.path.join(foldername, filename), arcname=os.path.join(os.path.relpath(foldername, os.path.dirname(folder)), filename))
    backupZip.close()

【讨论】:

  • 注意:你应该避免在函数内部使用imports。将 放在模块/脚本的开头。
  • @Bakuriu 感谢您的意见 - 请您帮忙解释一下为什么这是更好的做法?任何其他关于缩短/优化的意见也将不胜感激。
  • 首先要避免重复。如果在一个模块中你有 3 个需要模块 os 的函数,你不想添加 import os 三次。此外,将导入放在文件的开头清楚地显示了程序的依赖关系。任何阅读它的人都可以立即知道是否需要一些 3rd 方库以及哪些。最后:隐藏导入意味着如果用户没有安装所需的库,ImportError 只有在调用函数时才会触发,这可能会使调试更加困难;最好尽早失败。
  • 在函数内部也不能使用通配符形式:from os import * 在函数定义中不起作用,但在模块级别起作用。
【解决方案2】:

如果您想避免影响整个过程的chdir,您可以使用relpath 获取从您的顶级文件夹开始的相对路径。

你可以使用类似的东西

def backupToZip(folder):

    import zipfile, os

    folder = os.path.abspath(folder) # make sure folder is absolute

    # Walk the entire folder tree and compress the files in each folder.  
    for foldername, subfolders, filenames in os.walk(folder):

        if foldername == folder:
             archive_folder_name = ''
        else:
             archive_folder_name = os.path.relpath(foldername, folder)

             # Add the current folder to the ZIP file.
             backupZip.write(foldername, arcname=archive_folder_name)

        # Add all the files in this folder to the ZIP file.
        for filename in filenames:
            backupZip.write(os.path.join(foldername, filename), arcname=os.path.join(archive_folder_name, filename))
    backupZip.close()

backupToZip('Sample Folder')

【讨论】:

  • 谢谢!这非常接近,只需添加backupZip = zipfile.ZipFile('backup.zip', 'w')。此外,它删除了被压缩的根文件夹,即它直接从 zipfile 到子文件夹 - 无论如何要保留根文件夹?
  • 弄清楚如何在下面的每个答案中保留根文件夹 - 谢谢大家。
【解决方案3】:
  1. 使用os.chdir 更改当前路径
  2. 确保os.walk的参数是相对路径

*使用os.chdir时要小心


import zipfile, os

def backupToZip(folder):

    cwdpath = os.getcwd() # save original path (*where you run this py file)

    saveToWhere = "tmp.zip"
    zf = zipfile.ZipFile(saveToWhere, mode='w')

    folder = os.path.abspath(folder) # make sure folder is absolute
    os.chdir(folder) # change to that absolute path

    # os.walk(relative_path)
    for foldername, subfolders, filenames in os.walk("./"):
        for filename in filenames:
            zf.write(os.path.join(foldername, filename))    
    zf.close()

    os.chdir(cwdpath) # back to original path

【讨论】:

  • 谢谢! - 这真的很接近,但除了在for filename in filesnames 之前缺少zf.write(foldername) 之外,它还出于某种原因压缩了本地磁盘。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-09-05
  • 2013-03-09
  • 2012-06-19
  • 1970-01-01
  • 2010-10-12
  • 2010-12-14
  • 1970-01-01
相关资源
最近更新 更多