Debugging and Testing Python Scripts
The backup script automates file archiving by combining directory management, dynamic filename generation, and shell command execution.
The Backup Workflow
A backup script is easier to debug when you treat it as a sequence of connected stages rather than as one large task. The workflow checks for a main backup directory, creates it when necessary, creates a date-based subdirectory when necessary, builds a filename from the current time and an optional comment, and then executes a zip command. Debugging means tracing these stages and checking the values produced at each one.
Directory Checks First
The script uses os.path.exists before os.mkdir for both directory levels. os.path.exists returns True when the directory exists and False when it does not. Applying not reverses that result, so the creation step runs only when the directory is missing. The same pattern is used first for the main backup directory and then for the date-based subdirectory inside it.
Tracing a missing directory
Determine what the directory-management stage does when the main backup directory is missing but the date-based subdirectory has not yet been checked.
- 1Check the main directory
os.path.existsreports False because the main backup directory is missing. - 2Reverse the result
The not operator makes the creation condition True.
- 3Create the main directory
os.mkdircreates the main backup directory. - 4Continue to the date directory
The script then checks whether the date-based subdirectory exists inside the main directory.
The workflow creates the missing parent directory before it proceeds to the date-based directory.
Building the Backup Name
The date and time serve different organizational purposes. The date is used to create the subdirectory, while the time and optional comment are used to form the archive filename. time.strftime formats these values without separators: %Y%m%d produces a year-month-day sequence, and %H%M%S produces an hour-minute-second sequence. os.sep supplies the path separator for the current operating system.
The comment follows a conditional path. The len function checks whether the comment contains any characters. If its length is zero, the filename contains the time and the .zip extension. If the length is not zero, the script replaces spaces in the comment with underscores before appending it to the filename. Replacing spaces is the sanitization step described in the workflow.
Two comment inputs
Compare the filename logic for an empty comment and for a comment containing spaces.
- 1Empty comment
len reports zero, so the filename uses the time and the .zip extension without a comment.
- 2Comment with spaces
len reports a nonzero value, so the script replaces every space with an underscore and appends the sanitized comment.
- 3Check the result
The resulting filename should match the selected branch and should not retain spaces from the comment.
The conditional logic produces one filename pattern for an empty comment and another for a nonempty, sanitized comment.
Following Execution
A useful trace records the key state after each stage: whether the main directory exists, whether the date-based subdirectory exists, what date and time strings were produced, what comment was entered, what sanitized comment was produced, and what command was assembled. The script's print statements expose directory creation and the zip command, allowing you to compare the intended workflow with the actual values.
Fixing Broken Execution
When a multi-step script stops before showing its directory or command output, first determine whether execution reached those print statements. A syntax problem prevents the intended workflow from continuing, so inspect the script's structure before investigating directory contents or shell results. After correcting the malformed part, trace the workflow again from the beginning and verify each stage with the available print statements.
Common mistake Creating a directory without checking whether it exists.
What it looks likeThe script calls os.mkdir even when a previous run already created the directory.
Why it failsRepeated runs can fail when creation is attempted for an existing directory.
Do this insteadUse os.path.exists and create the directory only when the existence check indicates that it is missing.
Common mistake Treating an empty comment as though it were a nonempty comment.
What it looks likeThe filename-building logic appends a comment even after the user presses Enter.
Why it failsThe empty-comment case is supposed to use only the time and the .zip extension.
Do this insteadUse len to distinguish a zero-length comment from a nonempty comment.
Common mistake Appending a comment without replacing spaces.
What it looks likeA comment such as Project notes is inserted into the filename unchanged.
Why it failsSpaces in filenames can cause problems in many contexts.
Do this insteadReplace spaces with underscores before appending the comment.
Common mistake Running the shell command without checking its result.
What it looks likeThe script executes os.system and assumes the backup succeeded.
Why it failsThe returned status code indicates whether execution succeeded or failed.
Do this insteadCheck the status code after execution; zero indicates success and any other value indicates failure.
Testing Input Variations
Testing should vary the input and compare the observed output with the expected directory and filename behavior. Start with an empty comment, then use a comment containing spaces, and then test a comment containing special characters. For each run, inspect the printed directory information, the generated filename, and the assembled zip command. If the result differs from the expectation, use the trace to locate the stage where the value changed incorrectly.
Create a test checklist for the backup workflow. For each input, record whether the main directory already exists, whether the date-based subdirectory already exists, what the comment length indicates, what sanitized comment should be produced, and whether the final status code indicates success.
Hints
- Include an empty comment.
- Include a comment with at least one space.
- Include a comment with special characters, as suggested by the testing guidance.
- Check the printed command rather than assuming the filename was assembled correctly.
Key Debugging Principles
- 1Check each directory with
os.path.existsbefore usingos.mkdir, for both the main directory and the date-based subdirectory. - 2Use the date to organize the backup subdirectory and the time plus optional comment to form the archive filename.
- 3Use len to separate the empty-comment case from the nonempty-comment case.
- 4Sanitize comments by replacing spaces with underscores before adding them to filenames.
- 5Print important values and inspect the
os.systemstatus code so that execution can be traced and backup success can be checked.
Key Takeaways
- A reliable backup workflow checks and creates directories before constructing the archive command.
- The date-based directory and time-based filename organize backups while allowing dynamic names.
- Conditional logic handles empty comments separately from comments that require space replacement.
- Print statements and status-code checks make it possible to trace execution and identify failures.
- Testing multiple comment inputs and repeated runs exposes directory, naming, and command-construction bugs.