In computing, I/O stands for Input/Output—i.e., input and output operations. Since programs and runtime data reside in memory and are executed by the CPU (an ultra-fast processing core), any data exchange with external devices (typically disks, networks, etc.) requires I/O interfaces.
For example, when you open a browser to access Sina’s homepage, the browser program retrieves the page via network I/O. First, the browser sends data to Sina’s server (telling it, “I want the homepage HTML”)—this outbound data transfer is called Output. The server then sends the webpage back to the browser—this inbound data reception is called Input. In most cases, a program’s I/O operation involves two data streams (Input and Output). However, single-directional I/O is also common: reading a file from disk into memory is purely an Input operation, while writing data to a disk file is purely an Output operation.
A critical concept in I/O programming is Stream—imagine a stream as a water pipe where data is the water, flowing in only one direction. An Input Stream carries data from external sources (disk, network) into memory, while an Output Stream sends data from memory to external destinations. For web browsing, at least two “pipes” must be established between the browser and Sina’s server to enable both sending and receiving data.
Since the CPU and memory operate far faster than peripheral devices, I/O programming faces a severe speed mismatch problem. For instance, writing 100MB of data to disk takes the CPU only 0.01 seconds to generate the data, but the disk may take 10 seconds to complete the write. How to resolve this? Two approaches exist:
The CPU waits—i.e., the program pauses execution of subsequent code, waits 10 seconds for the 100MB to be written to disk, then resumes. This is called synchronous I/O.
The CPU does not wait—it simply tells the disk, “Take your time writing; I’ll go do other things.” Subsequent code executes immediately. This is called asynchronous I/O.
The core difference between synchronous and asynchronous I/O is whether the program waits for the I/O operation to complete. A real-world analogy:
Clearly, asynchronous I/O delivers far higher performance than synchronous I/O—but it comes with a complex programming model. You must track when the “hamburger is ready,” and notification mechanisms vary:
In short, asynchronous I/O is vastly more complex than synchronous I/O.
All I/O operations are provided by the operating system (OS). Every programming language encapsulates the OS’s low-level C interfaces for ease of use—and Python is no exception. We will discuss Python’s I/O programming interfaces in detail later.
Note: This chapter focuses exclusively on synchronous I/O. Asynchronous I/O, due to its high complexity, will be covered later when we discuss server-side programming.