Trying_hard
Trying_hard

Reputation: 9501

Archive / Zipfile python

The zipfile example in the lesson text stores the full path of the files that it saves to the zipfile. Normally, however, zipfiles contain only a relative pathname (you will see that when the names are listed after the zipfile is created, the "v:\" has been removed).

In this project, write a function that takes a directory path and creates an archive of the directory only. For example, if the same path were used as in the example ("v:\workspace\Archives\src\archive_me"), the zipfile would contain "archive_me\groucho" "archive_me\harpo" and "archive_me\chico." Note that zipfile.namelist() always uses forward slashes in what it returns, a fact you will need to accommodate when comparing observed and expected.

The base directory ("archive_me" in the example above) is the final element of the input, and all paths recorded in the zipfile should start with the base directory.

If the directory contains subdirectories, the subdirectory names and any files in the subdirectories should not be included. (Hint: You can use isfile() to determine if a filename represents a regular file and not a directory.)

I have the code below:

 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()

I am getting the error of "IOError: [Errno 21] Is a directory: 'archive_me'" I know this is caused by the me trying to zip an archive.... but I am not sure how to correct this. how do I get just the file to zip and past the test?

Thanks

Upvotes: 0

Views: 716

Answers (2)

Peter Party Bus
Peter Party Bus

Reputation: 2466

The way it is written right now you are closing the zipfile after every iteration of the for loop. Also your zipfile is named the same as your target dir, try this:

#!/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()

Upvotes: 0

reece
reece

Reputation: 8145

See the hint in your question (presumably homework related) and think about how it relates to the IOError you are seeing.

Some other hints/tips:

  1. try printing information as you are processing things rather than printing everything at once -- this will help track down errors and give the user an indication of progress;

  2. see if you can locate where the error is generated, and give better feedback to the user;

  3. think of each function as doing one job and see how that relates to what my_archive is doing (both in how it will be used under test and in real-world usage);

  4. names of functions should be descriptive of what they do -- a usual pattern is verb_noun.

Upvotes: 0

Related Questions