Date and Time Formatting with the time Module
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.
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
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?
- 1Start with the list
The list contains the two source directory paths as separate items.
- 2Join with a space
The
join()method places one space between the list items and produces one command-ready string. - 3Insert 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')- 1The timestamp supplies the archive's time-based name.
- 2
os.sepkeeps the path construction aligned with the operating system. - 3The command receives the target archive followed by the source directories.
- 4
os.system()passes the command to the shell. - 5The conditional verifies the command result instead of assuming that the archive was created.
- Import os for
os.sepandos.system(). - Import time for
time.strftime(). - Store the directories to include in the backup.
- Store the directory where the archive will be created.
- Format the current date and time as year, month, day, hour, minute, and second.
- Construct the archive path with the operating system's separator.
- Convert the source list into one space-separated string.
- Build the recursive zip command.
- Display the command before executing it.
- Execute the command and store the returned value.
- A return value of 0 selects the success message.
- A non-zero return value selects the failure message.
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.
- 1Format the timestamp
time.strftime()produces 20240115143022. - 2Construct the target
Linux uses a forward slash, so the target becomes /home/user/backups/20240115143022.zip.
- 3Join the sources
The source list becomes /home/user/docs /home/user/photos.
- 4Build the command
The command becomes zip -r /home/user/backups/20240115143022.zip /home/user/docs /home/user/photos.
- 5Execute 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
Common mistake Hardcoding one directory separator
What it looks liketarget = target_dir + '/' + timestamp + '.zip'Why it failsThe source emphasizes that Windows uses a backslash while macOS and Linux use a forward slash.
Do this insteadUse target_dir + os.sep + timestamp + '.zip'.Common mistake Using a fixed archive name
What it looks liketarget = target_dir + os.sep + 'backup.zip'Why it failsA fixed name can overwrite an earlier backup instead of preserving timestamped archives.
Do this insteadInclude the string returned by time.strftime() in the filename.
Common mistake Passing the source list directly into the command
What it looks likecommand = 'zip -r {0} {1}'.format(target, source)Why it failsThe source list needs to become a space-separated string for the command.
Do this insteadCreate source_list with ' '.join(source), then insert source_list into the command.
Common mistake Assuming the command succeeded
What it looks likeos.system(command) print('Backup succeeded')Why it failsThe program should use the return value from
os.system()to distinguish success from failure.Do this insteadStore the return value and compare it with 0.
Common mistake Running without customizing paths
What it looks likeUsing the example source and target_dir values unchanged.
Why it failsThe source instructs you to customize source and
target_dirfor your own system.Do this insteadChoose 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
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.sepsupplies 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.