Redis with Python
Use Redis in Python with redis-py. Install, connect, and work with strings, hashes, lists, and more.
Installation
Install redis-py with pip:
For better performance, install the optional hiredis parser. It replaces the pure-Python response parser with a C extension and is faster under high throughput:
Connecting
Default connection
redis.Redis() connects to 127.0.0.1 on port 6379, database 0, with no password:
Connecting with host, port, and password
Setting decode_responses=True makes the client return strings instead of bytes. This is usually what you want.
Connecting with a URL string
redis.from_url() accepts a Redis URL, which is convenient for reading connection details from an environment variable:
SSL/TLS connections
For managed Redis services that require TLS, pass ssl=True:
Or via URL:
The rediss:// scheme (with double s) enables TLS.
Strings
Strings are the most common Redis type. Use them for caching, counters, and session tokens.
Counters
INCR and DECR increment and decrement integer values atomically:
Bulk operations
MSET and MGET write and read multiple keys in a single round trip:
Hashes
Hashes store field-value pairs under a single key. They are well suited for representing objects where you need to read or update individual fields.
hmset is deprecated since Redis 4.0. Use hset with the mapping argument instead.
Lists
Lists are ordered sequences of strings. New elements can be added to either end, making them useful for queues and activity feeds.
A common pattern for a recent activity feed: push new events with lpush and trim the list to a fixed size:
Sets
Sets store unique, unordered values. They are useful for tracking memberships, tags, and deduplication.
Set operations
Sorted sets
Sorted sets associate a floating-point score with each member. Members are always returned in score order. They are commonly used for leaderboards, rate limiting windows, and priority queues.
Key expiry and TTL
Pipelining
Each Redis command normally requires a round trip to the server. Pipelining batches multiple commands into a single network call, which cuts latency significantly when you need to run many commands together.
The context manager calls execute() for you when the block exits. Commands inside the pipeline are queued locally and sent to Redis in one batch.
You can also read results back from a pipeline:
For atomic operations, use pipe.watch() to implement optimistic locking with MULTI/EXEC. For simpler atomicity requirements, Lua scripts via r.eval() are often cleaner.
Connection pooling
By default, each redis.Redis() instance creates its own connection. In a web application handling concurrent requests, you want to reuse connections instead of opening a new one per request.
ConnectionPool manages a pool of connections shared across threads:
Create the pool once at application startup and share the r instance (or create new Redis instances from the same pool). The pool is thread-safe.
For URL-based configuration:
Error handling
The most common exceptions come from the redis.exceptions module:
ResponseError covers cases like calling a list command on a string key, or exceeding memory limits. Set socket_connect_timeout and socket_timeout on the connection to avoid blocking indefinitely when Redis is slow or unreachable.
Async support
redis-py includes a built-in async client for use with asyncio. The API mirrors the synchronous client:
The async client supports the same commands, pipelining, connection pooling, and pub/sub as the sync client. Use it in FastAPI, Starlette, or any other asyncio-based application.
Quick reference
| Command | Description |
|---|---|
r.set(key, value, ex=n) | Set a string with optional TTL in seconds |
r.get(key) | Get a string value |
r.mset({k: v, ...}) | Set multiple keys at once |
r.mget(k1, k2, ...) | Get multiple keys at once |
r.incr(key) | Increment an integer value |
r.hset(key, mapping={...}) | Set hash fields |
r.hgetall(key) | Get all hash fields and values |
r.lpush(key, val) | Prepend to a list |
r.rpush(key, val) | Append to a list |
r.lrange(key, 0, -1) | Get all list elements |
r.sadd(key, *members) | Add to a set |
r.smembers(key) | Get all set members |
r.zadd(key, {member: score}) | Add to a sorted set |
r.zrange(key, 0, -1, rev=True) | Get sorted set members by score |
r.expire(key, seconds) | Set a TTL on an existing key |
r.ttl(key) | Get remaining TTL in seconds |
r.pipeline() | Open a pipeline context |
redis.ConnectionPool(...) | Create a shared connection pool |