HTTP Requests and Response Objects
The call response.read() is the point at which the complete file is brought into memory.
From Remote Bytes to Local Storage
Downloading an image, video, or another non-text file means copying its bytes from a remote URL to a file on your local disk. The basic urllib pattern has two stages: read the complete response into memory, then write those bytes to a local file using binary write mode.
The Request and Response Sequence
The expression urllib.request.urlopen(url) sends the request associated with the URL and gives the program a response object. Calling read() on that response retrieves the entire file body. In this pattern, the body is then held in memory as data before it is written to disk.
import urllib.request
response = urllib.request.urlopen(url)
data = response.read()
with open(filename, 'wb') as output_file:
output_file.write(data)- 1First,
urllib.request.urlopen(url)obtains a response object. - 2Next,
response.read()loads the entire response body into memory as data. - 3The local file is opened with wb, which selects binary write mode.
- 4Finally,
output_file.write(data)writes the downloaded data to the local file.
urlopen(url)obtains the response object for the URL.read()retrieves the entire file into data.open(filename, 'wb')opens the local destination for binary writing.write(data)copies the downloaded bytes into the local file.
Reading the Complete Response
The call response.read() is the point at which the complete file is brought into memory. The variable data represents the downloaded binary content that will later be passed to write(). This makes the pattern straightforward: retrieve all the bytes first, then save them.
Why wb Protects Binary Data
| Mode | Use in this pattern | Result for binary data |
|---|---|---|
| wb | Opens the local destination for binary writing | Preserves the downloaded bytes for the file copy |
| w | Text write mode | Can corrupt binary data |
The destination file must use binary write mode when the downloaded content is binary.
The b in wb indicates binary mode, and the w indicates writing. For an image, video, or another non-text file, the downloaded content must be written byte for byte. The source specifically identifies wb as essential and warns that text mode, w, will corrupt binary data.
with open(filename, 'w') as output_file:
output_file.write(data)The destination uses text mode.
with open(filename, 'wb') as output_file:
output_file.write(data)The destination uses binary write mode.
A Complete Download Pattern
Saving a Binary File Locally
Retrieve a binary file from url and save it using the local name filename.
- 1Obtain the response
Call
urllib.request.urlopen(url)to obtain the response object associated with the remote URL. - 2Read the response body
Call
response.read()and store the complete downloaded content in data. - 3Open the destination
Open filename with wb so the local file is prepared for binary writing.
- 4Write the bytes
Pass data to
output_file.write()to copy the downloaded binary content to the local file.
The binary file has been copied from the URL into the local file, provided that the complete file fits within available RAM.
Trace the variables from left to right: url identifies the remote location, response refers to the returned response object, data holds the complete downloaded file in memory, and output_file represents the local destination opened for binary writing.
Mistakes That Damage Downloads
Common mistake Opening the destination with w instead of wb
What it looks likewith open(filename, 'w') as output_file:Why it failsText mode can corrupt binary data.
Do this insteadUse open(filename, 'wb') when writing the downloaded binary content.
Common mistake Assuming read() avoids memory usage
What it looks likedata = response.read()Why it failsThis call downloads the entire file into memory before it is written.
Do this insteadUse this simple pattern for files smaller than available RAM.
Common mistake Writing before reading the response body
What it looks likeoutput_file.write(response)Why it failsThe source pattern reads the response body into data before passing the downloaded content to
write().Do this insteadCall data = response.read(), then write data to the binary destination.
Check Your Understanding
You need to retrieve a non-text file from url and save it as filename. Identify the correct mode for the local file and arrange the operations in the correct order.
Hints
- First obtain a response object with
urllib.request.urlopen(url). - Then call
read()and store the complete result in a variable. - Use binary write mode rather than text write mode.
What do you think happens?
What happens to memory when response.read() is used in this download pattern?
Reveal answer
The complete file is loaded into memory.
The source pattern uses response.read() to download the entire file into memory before writing it with open(filename, 'wb').write(data).
Key Takeaways
- 1
urllib.request.urlopen(url)provides a response object for the remote URL. - 2
response.read()retrieves the complete binary file into memory. - 3
open(filename, 'wb')opens the local destination in binary write mode. - 4Text mode, w, can corrupt binary data, so wb is essential for binary downloads.
- 5The complete-file-in-memory pattern is suitable for files smaller than available RAM.
At a glance
- A binary download copies bytes from a remote URL to a local file.
urllib.request.urlopen(url)returns a response object, andresponse.read()loads the complete response body into memory.- The local destination must be opened with wb so binary data is written without text-mode corruption.
- Because
read()loads the entire file at once, this pattern requires the file to fit within available RAM.