Typing Stubs for Redis
types-redis is a PEP 561 type stub package from the Python 'typeshed' project, providing static type annotations for the popular 'redis-py' library. It enables type-checking tools like MyPy, Pyright, and PyCharm to analyze code that uses the `redis` package, enhancing code quality and developer experience. This version, 4.6.0.20241004, aims to provide accurate annotations for redis==4.6.0. Typeshed stub packages are automatically released to PyPI frequently, often up to once a day.
Warnings
- breaking The `redis` package (redis-py) now includes its own type annotations/stubs starting from version 5.0.0. If you are using `redis>=5.0.0`, you should uninstall `types-redis` to avoid conflicts and redundant stubs. Continued use may lead to type-checking issues.
- gotcha `types-redis` versions are linked to `redis-py` versions. For example, `types-redis==4.6.0.YYYYMMDD` is designed for `redis-py==4.6.0`. Using mismatched major/minor versions (e.g., `types-redis` for `redis-py 4.x.x` with `redis-py 3.x.x` or `redis-py 5.x.x`) can lead to incorrect or missing type hints.
- gotcha Type stubs provided by typeshed, including `types-redis`, might be 'partial,' meaning some less common features or specific edge cases might have `Any` annotations or lack full type coverage. If you find missing annotations, contributions to typeshed are encouraged.
- gotcha Older versions of type checkers (e.g., MyPy, Pyright) might not fully support newer Python typing features used in `types-redis` stubs. This could lead to silent loss of type checking precision (e.g., `Any` types appearing unexpectedly) or outright errors.
- gotcha Early versions of `redis.asyncio` in `redis-py` had some type definition issues, which also affected `types-redis`. While many have been resolved, unexpected type errors might still occur with specific `redis-py` and `types-redis` combinations when using the async client.
Install
-
pip install types-redis -
pip install redis 'redis[hiredis]' types-redis
Imports
- Redis
from redis import Redis
- AsyncRedis
from redis.asyncio import Redis as AsyncRedis
Quickstart
import redis
from typing import Optional, Any
import os
def get_redis_client() -> redis.Redis[Any]:
# In a real application, you'd get connection details from environment variables or a configuration system.
# Using os.environ.get for quickstart, assuming Redis is running locally on default port.
host = os.environ.get('REDIS_HOST', 'localhost')
port = int(os.environ.get('REDIS_PORT', 6379))
db = int(os.environ.get('REDIS_DB', 0))
print(f"Connecting to Redis at {host}:{port}/{db}")
# types-redis provides the type hints for the Redis client.
return redis.Redis(host=host, port=port, db=db, decode_responses=True)
def set_and_get_value(client: redis.Redis[Any], key: str, value: str) -> Optional[str]:
client.set(key, value)
result: Optional[str] = client.get(key)
print(f"Set '{key}':'{value}', Retrieved: '{result}'")
return result
def increment_counter(client: redis.Redis[Any], key: str) -> int:
initial_value = client.setnx(key, 0) # Set if not exists, returns 1 if set, 0 otherwise
current_count: int = client.incr(key)
print(f"Incremented '{key}' to {current_count}")
return current_count
if __name__ == "__main__":
# Ensure a Redis server is running, e.g., via docker: docker run -p 6379:6379 -it redis:latest
try:
r_client = get_redis_client()
r_client.ping() # Test connection
print("Successfully connected to Redis!")
user_id_key: str = "user:profile:101"
user_data: str = "{'name': 'Jane Doe', 'email': 'jane.doe@example.com'}"
set_and_get_value(r_client, user_id_key, user_data)
page_views_key: str = "app:metrics:page_views"
increment_counter(r_client, page_views_key)
increment_counter(r_client, page_views_key)
# Example of using a typed command return value
all_keys: list[str] = r_client.keys('user:*')
print(f"Found user keys: {all_keys}")
except redis.exceptions.ConnectionError as e:
print(f"Could not connect to Redis: {e}. Please ensure Redis server is running.")
except Exception as e:
print(f"An unexpected error occurred: {e}")
finally:
# Clean up example keys (optional)
if 'r_client' in locals() and r_client.ping(): # Check if connected before deleting
r_client.delete(user_id_key, page_views_key)
print("Cleaned up example keys.")