Date and Time Formatting with the time Module
A backup program automates file archiving by using Python to construct and execute a zip command with a timestamped filename.
Why Timestamped Backups Matter
Manually backing up files is tedious and error-prone. You might forget a directory, overwrite an earlier backup, or use an inconsistent filename. A Python backup program automates the process by selecting source directories, creating an archive name based on the current date and time, and executing the backup command.
The central idea is to turn the current date and time into a predictable filename, then place that filename into a zip command executed by the operating system.
What do you think happens?
What should happen when the backup program runs?
Reveal answer
Answer: It prints the command, executes it, and reports success or failure.
The program constructs a zip command, displays the command it is about to execute, passes it to os.system(), and checks the returned value. A return value of 0 indicates success; a non-zero value indicates failure.
From Clock to Archive Name
The time.strftime() function converts the current date and time into a formatted string. The format string %Y%m%d%H%M%S contains codes for the year, month, day, hour, minute, and second. When those codes are replaced with the current values, the result can be used as part of the archive filename.
| Code | Meaning |
|---|---|
| %Y | Year |
| %m | Month |
| %d | Day |
| %H | Hour |
| %M | Minute |
| %S | Second |
Format codes used to build the timestamp string described in the source.
A possible output is a timestamp such as 20240115143022. The exact value depends on when the program runs.Portable Backup Paths
A path combines a directory with a filename. The directory separator is not written the same way on every operating system: Windows uses a backslash, while macOS and Linux use a forward slash. Python provides os.sep as the separator appropriate for the operating system where the program is running.
The construction pattern is the same on every supported operating system: target directory, os.sep, timestamp, and the .zip extension. The visible separator changes with the operating system, but the backup program keeps the same overall behavior.
Constructing the Zip Command
The program builds the zip command as a string. It combines the zip utility, the recursive option, the target archive filename, and the source directories. The -r option tells zip to work recursively through subdirectories.
Joining Source Directories
Suppose source contains two entries: /home/user/docs and /home/user/photos. What string does ' '.join(source) create?
Start with the list: The list contains the two source directory paths as separate items.
Join with a space: The join() method places one space between the list items and produces one command-ready string.
Insert into the command: The resulting string is used as the source portion of the zip command.
'/home/user/docs /home/user/photos'
Checking the Command Result
os.system() executes the command as if it had been typed into a terminal or command prompt. After the command finishes, os.system() returns a value. A return value of 0 means the command succeeded. A non-zero value means it failed. The program uses this result to choose a success or failure message.
Complete Backup Flow
The following is a generated implementation assembled from the source-described steps. It selects source directories, formats a timestamp, constructs the target path with os.sep, joins the source list, builds the zip command, executes it, and checks the return value.
import os import time source = ['docs', 'photos'] target_dir = 'backup' timestamp = time.strftime('%Y%m%d%H%M%S') target = target_dir + os.sep + timestamp + '.zip' source_list = ' '.join(source) command = 'zip -r {0} {1}'.format(target, source_list) print(command) result = os.system(command) if result == 0: print('Backup succeeded') else: print('Backup failed')
Tracing Concrete Values
Trace the program on a Linux system when target_dir is /home/user/backups, source contains /home/user/docs and /home/user/photos, and the formatted timestamp is 20240115143022.
Format the timestamp: time.strftime() produces 20240115143022.
Construct the target: Linux uses a forward slash, so the target becomes /home/user/backups/20240115143022.zip.
Join the sources: The source list becomes /home/user/docs /home/user/photos.
Build the command: The command becomes zip -r /home/user/backups/20240115143022.zip /home/user/docs /home/user/photos.
Execute and inspect: os.system() executes the command. If it returns 0, the program prints the success message; otherwise it prints the failure message.
The program sends a timestamped recursive zip command to the shell and reports the result returned by os.system().
Mistakes to Avoid
Hardcoding one directory separator
The source emphasizes that Windows uses a backslash while macOS and Linux use a forward slash.
Fix:
Use target_dir + os.sep + timestamp + '.zip'.Using a fixed archive name
A fixed name can overwrite an earlier backup instead of preserving timestamped archives.
Fix:
Include the string returned by time.strftime() in the filename.Passing the source list directly into the command
The source list needs to become a space-separated string for the command.
Fix:
Create source_list with ' '.join(source), then insert source_list into the command.Assuming the command succeeded
The program should use the return value from os.system() to distinguish success from failure.
Fix:
Store the return value and compare it with 0.Running without customizing paths
The source instructs you to customize source and target_dir for your own system.
Fix:
Choose source directories and a target directory that exist on the system where the program will run.
Practice the Trace
Assume timestamp is 20251231115959, target_dir is archive, and source is ['work', 'notes']. Write the target path, the joined source string, and the complete zip command. Then state which message the program prints when os.system() returns 0.
Hints
- Build the target from target_dir, os.sep, timestamp, and .zip.
- Use a single space between the two source entries.
- The command begins with zip -r.
- A return value of 0 selects the success branch.
What do you think happens?
If the command returns a non-zero value, which branch should run?
Reveal answer
Answer: The failure branch.
The program treats 0 as success and any non-zero return value as failure.
Practical Design Lessons
This backup program separates responsibilities. Python handles file selection, timestamped naming, path construction, command construction, and result checking. The zip utility handles the actual recursive compression. This division lets the program use an established operating-system tool rather than implementing compression itself.
A useful automation script does more than start an operation. It prepares clear inputs, uses portable system details, executes the operation, and verifies the result.
Key Takeaways
- time.strftime('%Y%m%d%H%M%S') converts the current date and time into a timestamp suitable for an archive filename.
- os.sep supplies the operating system's directory separator instead of forcing one separator into the program.
- The zip command is built from the recursive option, target archive path, and a space-separated source list.
- os.system() passes the command to the shell and returns 0 for success or a non-zero value for failure.
- A complete backup flow constructs the archive name, builds the command, executes it, and checks the result.