Polling repeatedly checks a resource to determine whether it is ready or has new data. It is straightforward, but frequent checks can waste CPU time or server resources when nothing has changed. section 3.3 section 9.3.2
Polling creates different costs in low-level sockets and web applications:
- A tight loop around non-blocking socket operations may repeatedly catch BlockingIOError, producing verbose, error-prone code and nearly 100% CPU usage. section 3.3
- HTTP polling sends requests at intervals even when the value has not changed, adding request and response load without providing new information. section 9.3.2
- Operating-system event notifications and WebSockets avoid repeated checks by notifying applications when socket data or updated values are available. section 3.3 section 9.3.2
Live user count
A page can poll an endpoint every few seconds for the current number of users. A WebSocket instead keeps one persistent connection and lets the server send a new count only when it changes. section 9.3.2
Listing 3.6 Catching and ignoring blocking IO errors
import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_address = ('127.0.0.1', 8000)
server_socket.bind(server_address)
server_socket.listen()
server_socket.setblocking(False)
connections = []
try:
while True:
try:
connection, client_address = server_socket.accept()
connection.setblocking(False)
print(f'I got a connection from {client_address}!')
connections.append(connection)
except BlockingIOError:
pass
for connection in connections:
try:
buffer = b''
while buffer[-2:] != b'\r\n':
data = connection.recv(2)
if not data:
break
else:
print(f'I got data: {data}!')
buffer = buffer + data
print(f"All the data is: {buffer}")
connection.send(buffer)
except BlockingIOError:
pass
finally:
server_socket.close()
Shows a non-blocking server that catches and ignores readiness errors while repeatedly checking sockets. section 3.3








