Python 压缩 / Zipfile

0 投票
2 回答
710 浏览
提问于 2025-04-17 18:31

在课程的示例中,zipfile会保存文件的完整路径。不过,通常情况下,zip文件里只会包含相对路径(你会发现,当创建zip文件后,文件名中会去掉“v:\”这样的部分)。

在这个项目中,你需要写一个函数,它接受一个目录路径,然后只把这个目录打包成一个压缩文件。比如,如果你用的路径和示例中的一样(“v:\workspace\Archives\src\archive_me”),那么生成的zip文件里会包含“archive_me\groucho”、“archive_me\harpo”和“archive_me\chico”。需要注意的是,zipfile.namelist()返回的路径总是使用正斜杠,这一点在你比较实际结果和预期结果时要特别留意。

基本目录(在上面的例子中是“archive_me”)是输入路径的最后一个部分,zip文件中记录的所有路径都应该以这个基本目录开头。

如果目录里有子目录,那么子目录的名字和子目录里的文件都不应该被包含在内。(提示:你可以用isfile()来判断一个文件名是否代表一个普通文件,而不是一个目录。)

我有以下代码:

 import os, shutil, zipfile, unittest

 def my_archive(path):
     x = os.path.basename(path)
     zf = zipfile.ZipFile(x, "w")
     filenames = glob.glob(os.path.join(x, "*"))
     print(filenames)
     for fn in filenames:
          zf.write(fn)
          zf.close
     zf = zipfile.ZipFile(path)
     lst =  zf.namelist()
     return(lst)
     zf.close()


 import os, shutil, zipfile, unittest
 import archive_dir

 class TestArchiveDir(unittest.TestCase):

     def setUp(self):
         self.parentPath = r"/Users/Temp"
         self.basedir = 'archive_me'
         self.path = os.path.join(self.parentPath,self.basedir)
         if not os.path.exists(self.path):
             os.makedirs(self.path)
         self.filenames = ["groucho", "harpo", "chico"]
         for fn in self.filenames:
             f = open(os.path.join(self.path, fn), "w")
             f.close()

     def test_archive_create(self):

         observed = archive_dir.my_archive(self.path)
         expected = ["archive_me/groucho", "archive_me/harpo", "archive_me/chico"]
         self.assertEqual(set(expected), set(observed))

     def tearDown(self):
         try:
             shutil.rmtree(self.parentPath, ignore_errors=True)
         except IOError:
             pass

 if __name__=="__main__":
     unittest.main()

我遇到了“IOError: [Errno 21] Is a directory: 'archive_me'”的错误。我知道这是因为我试图压缩一个目录……但我不确定该如何修正。怎样才能只压缩文件并通过测试呢?

谢谢

2 个回答

0

现在的写法是你在每次循环结束后都关闭了压缩文件。而且你的压缩文件名字和目标文件夹是一样的,试试这样写:

#!/usr/bin/python3

import zipfile
import os
import glob

def archdir(dir):
    x = os.path.basename(dir) + ".zip"
    zf = zipfile.ZipFile(x, "w")
    filenames = glob.glob(os.path.join(os.path.basename(dir), "*"))
    print(filenames)
    for fn in filenames:
        zf.write(fn)
    zf.close()
0

看看你问题中的提示(可能和作业有关),想想它和你遇到的IOError有什么关系。

这里有一些其他的提示:

  1. 在处理事情的时候,试着逐步打印信息,而不是一次性打印所有内容——这样可以帮助你找到错误,并让用户知道进展如何;

  2. 看看能否找到错误产生的地方,并给用户提供更好的反馈;

  3. 把每个函数看作是完成一项工作的,想想这和my_archive的作用有什么关系(无论是在测试中还是在实际使用中);

  4. 函数的名字应该能清楚地描述它们的功能——通常的命名方式是动词_名词

撰写回答