Loop Control and Break Statements
The break statement is not the mechanism that reduces memory usage by itself.
Try it: while Loops, break and continue
How a while loop re-evaluates its condition before every pass, how break leaves the loop at once, how continue jumps back to the condition, how a sentinel value ends a while True loop, and why a loop whose condition never becomes False runs forever.
How it works
- Evaluate the condition. If it is False, skip the body and continue after the loop.
- If it is True, run the body from the top, then go back and evaluate the condition again.
- continue skips the rest of the body and goes straight back to the condition check.
- break leaves the loop immediately; the condition is not checked again (while True loops rely on it, e.g. stopping at a sentinel like 'done').
- If nothing in the body can make the condition False, the loop never ends; the lab's guard stops it after N iterations and says so.
Default run (21 steps): Ready: Countdown. A while loop checks its condition before every pass. … Finished after 5 iterations and 6 condition checks.
Simplified: The lab's own small Python interpreter runs a fixed, hand-written script (you choose the variant and the values, never the code); nothing is executed as real Python. Every script was run in CPython 3.12 with the same inputs and the lab reproduces its output and error messages. input() returns the lines you type in the list, one per call (the prompt is not printed), and raises EOFError when they run out, like a closed keyboard stream. The guard is the lab's, not Python's.
Loading the simulation…
Why Whole-File Loading Fails
When a program loads an entire large file into memory, the file occupies memory all at once. As file size grows, this can exhaust available memory, causing crashes or slowdowns. Buffered reading uses a different strategy: the program retrieves one fixed-size block, writes that block to disk, and only then retrieves the next block.
The goal is not to make the file smaller. The goal is to limit how much of it is held in memory at one time.
The Buffered Transfer Cycle
A buffered transfer repeats a small cycle. First, the source supplies a block whose size is controlled by buffer_size. Next, that block is written to disk. After the write, the program asks the source for another block. This continues until the source returns empty data.
Three-Block Transfer
Trace a source containing three sequential blocks: Block A, Block B, and Block C.
- 1First read
The source supplies Block A. The buffer holds Block A, and the program writes Block A to disk.
- 2Second read
After Block A has been written, the source supplies Block B. The buffer now holds Block B, and the program writes Block B to disk.
- 3Third read
The same process retrieves and writes Block C.
- 4Final read
The source has no remaining data, so the read produces empty data. The loop uses this signal to stop.
The disk receives all three blocks sequentially, while memory holds only the current block during each transfer.
Reading Until the Source Ends
The core loop pattern uses while True to keep requesting blocks. Each iteration calls img.read(buffer_size). The loop cannot stop merely because one block has been processed; it must request the next block and inspect the result. When read() returns empty data, the source has reached the end of the file. The break statement then exits the loop immediately.
while True:
block = img.read(buffer_size)
if not block:
break
output.write(block)- 1The while True statement creates a loop that continues until a break statement is reached.
- 2The read operation retrieves the next block.
- 3The condition checks whether the returned block is empty.
- 4The break statement transfers control out of the loop when no block remains.
- 5A nonempty block is written to the output before the next iteration begins.
- Keep requesting sequential blocks.
- Read one block using the chosen buffer size.
- An empty result means that no data remains.
- Exit the loop when the end-of-file signal is received.
- Write the current block before requesting the next one.
Writing Blocks Safely
The output operation belongs inside the loop, immediately after the program confirms that a nonempty block was read. This makes the transfer incremental: each block is written before the next block is retrieved. When writing downloaded files to disk, use binary mode, written as wb. Binary mode is the required mode for this technique.
| Approach | Memory behavior | Transfer behavior |
|---|---|---|
| Load the entire file | The entire file is held in memory | All data is obtained at once |
| Buffered reading | One fixed-size block is held at a time | Each block is written before the next is retrieved |
Buffered reading limits the amount of file data held in memory during transfer.
Mistakes with Loop Control
Common mistake Loading the entire large file before writing it
What it looks likeTreating the whole file as one object in memory
Why it failsThe file can consume excessive memory and cause crashes or slowdowns.
Do this insteadRead fixed-size blocks and write each block before retrieving the next.
Common mistake Omitting the end-of-file check
What it looks likeContinuing after read() returns empty data
Why it failsThe loop lacks the termination signal identified by the buffered-reading pattern.
Do this insteadCheck for empty data and use break to leave the loop.
Common mistake Writing the block after requesting another block
What it looks likeReading repeatedly without writing the current block
Why it failsThe program does not follow the incremental read-then-write cycle.
Do this insteadWrite each nonempty block before the next read.
Common mistake Using text mode for downloaded binary data
What it looks likeOpening the destination without binary mode
Why it failsThe source specifically requires binary mode for writing downloaded files.
Do this insteadUse wb when writing downloaded files to disk.
Practice the Control Flow
A source contains four sequential blocks. Describe what happens on each iteration of a while True loop that reads with img.read(buffer_size), stops when the returned data is empty, and writes each nonempty block to output. Include the point at which break executes.
Hints
- Track the current block in memory separately from the blocks already written to disk.
- After the fourth block is written, consider what the next read returns.
- The empty result is the termination signal.
What do you think happens?
After the final nonempty block has been written, what should the next read produce?
Reveal answer
Empty data
The source states that read() returns empty data at end-of-file. The loop then uses break to stop.
Practical Reach
Buffered reading is useful for real-world network applications because it allows programs to download files of any size without crashing or exhausting system resources. The essential design is consistent: keep only a fixed-size block in memory, write it to disk, and stop when the source reports that no data remains.
Key Takeaways
- Loading an entire large file into memory can cause slowdowns, crashes, or exhausted system resources.
- Buffered reading retrieves data in fixed-size blocks and writes each block to disk before retrieving the next.
- A while True loop can process sequential blocks when it checks each read result for empty data.
- An empty result from
read()signals end-of-file, and break exits the loop. - Downloaded files should be written in binary mode using wb, with a buffer size between 100 KB and 1 MB.