Python 压缩 / Zipfile
在课程的示例中,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 个回答
现在的写法是你在每次循环结束后都关闭了压缩文件。而且你的压缩文件名字和目标文件夹是一样的,试试这样写:
#!/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()
看看你问题中的提示(可能和作业有关),想想它和你遇到的IOError有什么关系。
这里有一些其他的提示:
在处理事情的时候,试着逐步打印信息,而不是一次性打印所有内容——这样可以帮助你找到错误,并让用户知道进展如何;
看看能否找到错误产生的地方,并给用户提供更好的反馈;
把每个函数看作是完成一项工作的,想想这和my_archive的作用有什么关系(无论是在测试中还是在实际使用中);
函数的名字应该能清楚地描述它们的功能——通常的命名方式是
动词_名词
。