Python项目使用非阻塞socket报错AttributeError: module 'socket' has no attribute 'setblocking'的解决方法及替代方案咨询
Hey there! Let's fix that error and walk through better ways to implement non-blocking sockets in Python.
AttributeError The problem is super straightforward: you're trying to call socket.setblocking() directly on the socket module, but this method doesn't belong to the module itself—it's a method for individual socket instances you create.
Here's the correct way to use it:
import socket # First create a socket object client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Now set it to non-blocking mode client_socket.setblocking(False)
This should resolve the AttributeError immediately.
If you're looking for more robust or scalable options beyond setblocking(False), here are three solid approaches:
1. Use the select Module (Classic Multiplexing)
The select module lets you monitor multiple sockets for read/write events, which is great for handling multiple connections without blocking. Here's a quick example for a server:
import socket import select # Set up a listening socket server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.setblocking(False) server_socket.bind(("localhost", 8080)) server_socket.listen(5) # Track sockets we want to read from read_sockets = [server_socket] while True: # Wait for activity (timeout after 0.1s to avoid hanging) readable, _, _ = select.select(read_sockets, [], [], 0.1) for sock in readable: # New connection if sock is server_socket: conn, addr = sock.accept() conn.setblocking(False) read_sockets.append(conn) print(f"New connection from {addr}") # Existing connection has data else: try: data = sock.recv(1024) if not data: # Client disconnected read_sockets.remove(sock) sock.close() else: print(f"Received: {data.decode()}") except BlockingIOError: # No data available right now—move on pass
2. Use asyncio (Modern Asynchronous IO)
For Python 3.4+, asyncio is the standard library's way to write async code. It's cleaner for large-scale concurrency and avoids manual error handling for blocking calls. Here's a simple async server example:
import asyncio async def handle_client(reader, writer): # Wait for data (non-blocking under the hood) data = await reader.read(1024) message = data.decode() addr = writer.get_extra_info("peername") print(f"Received {message!r} from {addr!r}") # Send response back writer.write(data) await writer.drain() # Clean up writer.close() await writer.wait_closed() async def main(): # Start an async server server = await asyncio.start_server(handle_client, "localhost", 8080) addr = server.sockets[0].getsockname() print(f"Serving on {addr}") # Run forever async with server: await server.serve_forever() asyncio.run(main())
3. Manual Flag Setting (Low-Level)
On Linux/macOS, you can use the fcntl module to directly set the non-blocking flag on the socket's file descriptor. On Windows, you'd use ctypes instead. Here's the Linux/macOS version:
import socket import fcntl import os client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Get current file descriptor flags current_flags = fcntl.fcntl(client_socket.fileno(), fcntl.F_GETFL) # Add the non-blocking flag fcntl.fcntl(client_socket.fileno(), fcntl.F_SETFL, current_flags | os.O_NONBLOCK)
- For simple one-off non-blocking operations: Stick with
setblocking(False)plustry/except BlockingIOError. - For handling multiple connections:
selectis a battle-tested classic, orasyncioif you want a more modern, readable approach. - For low-level control: Use the manual flag setting method (but only if you really need it).
内容的提问来源于stack exchange,提问作者eliotz

