>A Byte of Python

The Solution

As the design of our program is now stable, we can write the code which is an implementation of our solution.

You will notice how we have converted our design into code in a step-by-step manner.

We first import the os and time modules to use some of the functionality of these modules. Then, we specify the files and directories to backup in the source list. The target directory is where we store all our backup files and this is specified by the target_dir variable. The name of the zip archive backup that we are going to create is the current date and time as returned by the time.strftime() function with the .zip extension and this archive is stored in the target_dir directory.

The time.strftime() function takes a specification like the one we have used in the above program. The %Y specification will be replaced by the year without the century. The %m specification will be replaced by the month as a decimal number between 01 and 12 for the current date, and so on. The complete list of such specifications can be found in the [Python Reference Manual] that comes with your Python distribution.

Then we create the name of the target zip file using the addition operator which concatenates the strings i.e. returns a string which combines those two strings. Then, we create a string zip_command which contains the command that we are going to execute. You can execute this command directly from the shell (Linux terminal or DOS prompt) to check if it works properly.

The zip command that we are using is like this - we use the option -q to indicate that the zip command should work quietly. The option -r indicates that the zip command should work recursively for directories i.e. it should include subdirectories and files within the subdirectories as well. The two options are combined to get -qr. The options are followed by the name of the zip archive to create, followed by the list of files and directories to backup. We convert the source list into a string using the join method of strings which we have already seen how to use.

Then, we finally run the command using the os.system function which runs the command as if it was run from the system i.e. the shell. It then returns 0 if the command was successfully. It will return an error number otherwise.

Depending on the outcome of the command we print an appropriate message and that's it, we have created a backup of our important files!

Now that we have a working backup script, we can use it whenever we want to take the backup of files. Linux/Unix users are advised to use the executable method we discussed earlier so that they can run the backup script anytime anywhere. This is called the operation phase or the deployment phase of the software.

The above program works properly, but (usually) first programs may not work exactly as you expect. For example, there might be problems if you have not designed the program properly or if you have not written the code according to the design or you might have made a mistake in typing. Appropriately, you will have to go back to the design phase or you will have to debug your program.

The first version at our script is good, but we can make some refinements to it so that it can work better. This is called the maintenance phase of the software.

One of the refinements I felt was useful is a better file-naming mechanism - using the time as the name of the file within a directory with the current date as time within the main backup directory. One advantage is that your backups are stored in a hierarchical manner and therefore much easier to manage. Another advantage is that the length of the filenames are much shorter this way. Another advantage is that separate directories will help you to check that you have taken a backup for each day since the directory will be created only if you have taken a backup that day.

The second version works fine, but when I do many backups, I am finding it hard to differentiate what the backups were for. For example, I might have made some major changes to a document, then I want to associate what those changes are with the name of the backup archive. This can be achieved by attaching a user-supplied comment to the name of the zip archive.

The fourth version must be a satisfactorily working script for most users, but there is always room for improvement. For example, you can include a verbosity level for the program where you can specify -v option to make your program more talkative, or you can backup additional files and directories specified on the command line using the sys.argv list.

One refinement I prefer is the use of the tar command instead of the zip command in Linux/Unix. One advantage is that when you use tar along with gzip, the backup is much faster and the archive size created is also much smaller. If I need to use this archive in Windows, then WinZip handles such .tar.gz files as well.

The command to use for utilising the tar is

tar = 'tar -cvzf %s %s -X /home/g2swaroop/bin/excludes.txt' % (dst,
	' '.join(srcdir))
        

where the options are explained below.