Python wrapper for hiredis that speeds up parsing of Redis multi bulk replies
npx @tessl/cli install tessl/pypi-hiredis@3.2.00
# hiredis
1
2
Python extension that wraps protocol parsing code in hiredis to significantly speed up parsing of Redis multi bulk replies. The library provides a Reader class for parsing replies from Redis data streams with support for Unicode decoding, customizable error handling, and efficient memory usage.
3
4
## Package Information
5
6
- **Package Name**: hiredis
7
- **Package Type**: pypi
8
- **Language**: Python
9
- **Installation**: `pip install hiredis`
10
- **Python Requirements**: Python 3.8+
11
12
## Core Imports
13
14
```python
15
import hiredis
16
```
17
18
Specific imports:
19
20
```python
21
from hiredis import Reader, pack_command, HiredisError, ProtocolError, ReplyError, PushNotification
22
```
23
24
## Basic Usage
25
26
```python
27
import hiredis
28
29
# Create a reader for parsing Redis replies
30
reader = hiredis.Reader()
31
32
# Feed data from Redis connection
33
reader.feed("$5\r\nhello\r\n")
34
35
# Extract parsed reply
36
reply = reader.gets() # Returns b'hello'
37
38
# Pack commands into Redis protocol format
39
packed = hiredis.pack_command(("SET", "key", "value"))
40
# Returns: b'*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n'
41
```
42
43
## Capabilities
44
45
### Redis Reply Parsing
46
47
The Reader class parses Redis protocol replies from data streams, providing efficient protocol parsing with configurable decoding and error handling.
48
49
```python { .api }
50
class Reader:
51
def __init__(
52
self,
53
protocolError: Callable[[str], Exception] = None,
54
replyError: Callable[[str], Exception] = None,
55
encoding: Optional[str] = None,
56
errors: Optional[str] = None,
57
notEnoughData: Any = False,
58
) -> None:
59
"""
60
Create a new Reader for parsing Redis replies.
61
62
Parameters:
63
- protocolError: Custom exception class/callable for protocol errors
64
- replyError: Custom exception class/callable for reply errors
65
- encoding: Text encoding for bulk data decoding (e.g., 'utf-8')
66
- errors: Error handling mode ('strict', 'replace', 'ignore', 'backslashreplace')
67
- notEnoughData: Custom sentinel returned when buffer lacks complete reply
68
"""
69
70
def feed(self, buf: Union[str, bytes], off: int = 0, len: int = -1) -> None:
71
"""
72
Feed data to the internal buffer for parsing.
73
74
Parameters:
75
- buf: Data to append to buffer (string or bytes)
76
- off: Starting offset in buffer (default: 0)
77
- len: Number of bytes to read (default: -1 for all)
78
"""
79
80
def gets(self, shouldDecode: bool = True) -> Any:
81
"""
82
Extract a reply from the buffer.
83
84
Parameters:
85
- shouldDecode: Whether to decode bulk data using configured encoding
86
87
Returns:
88
- Parsed reply data, or False if buffer lacks complete reply
89
- Returns notEnoughData sentinel if configured
90
"""
91
92
def setmaxbuf(self, maxbuf: Optional[int]) -> None:
93
"""
94
Set maximum buffer size to control memory usage.
95
96
Parameters:
97
- maxbuf: Maximum buffer size in bytes, None for unlimited
98
"""
99
100
def getmaxbuf(self) -> int:
101
"""
102
Get current maximum buffer size.
103
104
Returns:
105
- Current maximum buffer size in bytes
106
"""
107
108
def len(self) -> int:
109
"""
110
Get length of data in internal buffer.
111
112
Returns:
113
- Number of bytes in buffer
114
"""
115
116
def has_data(self) -> bool:
117
"""
118
Check if buffer contains any data.
119
120
Returns:
121
- True if buffer has data, False otherwise
122
"""
123
124
def set_encoding(
125
self, encoding: Optional[str] = None, errors: Optional[str] = None
126
) -> None:
127
"""
128
Update encoding configuration for bulk data decoding.
129
130
Parameters:
131
- encoding: Text encoding (e.g., 'utf-8'), None to disable decoding
132
- errors: Error handling mode ('strict', 'replace', 'ignore', 'backslashreplace')
133
"""
134
```
135
136
### Command Packing
137
138
Convert Python command tuples into Redis protocol format for transmission to Redis servers.
139
140
```python { .api }
141
def pack_command(cmd: Tuple[Union[str, int, float, bytes, memoryview], ...]) -> bytes:
142
"""
143
Pack command arguments into Redis protocol format.
144
145
Parameters:
146
- cmd: Tuple containing command and arguments
147
Supports: str, int, float, bytes, memoryview
148
149
Returns:
150
- Bytes object containing packed Redis protocol command
151
152
Raises:
153
- TypeError: If command contains unsupported argument types
154
"""
155
```
156
157
### Error Handling
158
159
Exception classes for different error conditions during Redis protocol parsing.
160
161
```python { .api }
162
class HiredisError(Exception):
163
"""Base exception class for all hiredis errors."""
164
165
class ProtocolError(HiredisError):
166
"""
167
Raised when protocol parsing fails due to corrupt data stream.
168
Indicates unrecoverable protocol state requiring reconnection.
169
"""
170
171
class ReplyError(HiredisError):
172
"""
173
Represents Redis error replies (-ERR responses).
174
This exception is returned by gets(), not raised.
175
"""
176
177
class PushNotification(list):
178
"""
179
Represents Redis push notifications in RESP3 protocol.
180
Extends list to contain notification data.
181
"""
182
```
183
184
### Version Information
185
186
```python { .api }
187
__version__: str
188
# Current package version string (e.g., "3.2.1")
189
```
190
191
## Usage Examples
192
193
### Unicode Decoding
194
195
```python
196
import hiredis
197
198
# Configure reader for UTF-8 decoding
199
reader = hiredis.Reader(encoding="utf-8", errors="strict")
200
reader.feed(b"$3\r\n\xe2\x98\x83\r\n") # UTF-8 snowman
201
reply = reader.gets() # Returns '☃' (string, not bytes)
202
```
203
204
### Custom Error Handling
205
206
```python
207
import hiredis
208
209
# Use custom exception classes
210
class MyProtocolError(Exception):
211
pass
212
213
class MyReplyError(Exception):
214
pass
215
216
reader = hiredis.Reader(
217
protocolError=MyProtocolError,
218
replyError=MyReplyError
219
)
220
221
# Protocol errors will raise MyProtocolError
222
# Reply errors will return MyReplyError instances
223
```
224
225
### Buffer Management
226
227
```python
228
import hiredis
229
230
reader = hiredis.Reader()
231
232
# Set buffer size limit
233
reader.setmaxbuf(1024 * 1024) # 1MB max
234
235
# Monitor buffer usage
236
print(f"Buffer size: {reader.len()} bytes")
237
print(f"Has data: {reader.has_data()}")
238
print(f"Max buffer: {reader.getmaxbuf()} bytes")
239
```
240
241
### Multi-Reply Processing
242
243
```python
244
import hiredis
245
246
reader = hiredis.Reader()
247
248
# Feed data containing multiple replies
249
reader.feed("$5\r\nhello\r\n$5\r\nworld\r\n")
250
251
# Extract all replies
252
replies = []
253
while True:
254
reply = reader.gets()
255
if reply is False: # No more complete replies
256
break
257
replies.append(reply)
258
259
print(replies) # [b'hello', b'world']
260
```
261
262
### Command Packing Examples
263
264
```python
265
import hiredis
266
267
# Basic command
268
cmd = hiredis.pack_command(("GET", "mykey"))
269
# Returns: b'*2\r\n$3\r\nGET\r\n$5\r\nmykey\r\n'
270
271
# Complex command with different data types
272
cmd = hiredis.pack_command((
273
"HSET", "hash", "field1", "value1",
274
b"field2", b"binary_value",
275
"field3", 42,
276
"field4", 3.14159
277
))
278
279
# Command with memoryview
280
data = memoryview(b"binary data")
281
cmd = hiredis.pack_command(("SET", "key", data))
282
```
283
284
## Performance Notes
285
286
- Provides significant performance improvements for parsing multi bulk replies
287
- Throughput improvements increase with reply size (up to 83x faster for large LRANGE operations)
288
- Reader instances are not thread-safe - use separate instances per thread
289
- Memory usage is controlled through buffer size limits
290
- Best used as a performance enhancement for Redis client libraries