A poor man's debugger for Python that provides elegant tracing without print statements.
npx @tessl/cli install tessl/pypi-pysnooper@1.2.00
# PySnooper
1
2
A poor man's debugger for Python that provides elegant tracing without print statements. PySnooper offers an alternative to traditional debugging with breakpoints by decorating functions or wrapping code blocks to get detailed execution logs showing line-by-line execution, variable changes, and timing information.
3
4
## Package Information
5
6
- **Package Name**: PySnooper
7
- **Language**: Python
8
- **Installation**: `pip install pysnooper`
9
10
## Core Imports
11
12
```python
13
import pysnooper
14
```
15
16
## Basic Usage
17
18
```python
19
import pysnooper
20
21
# Decorator usage - trace entire function
22
@pysnooper.snoop()
23
def number_to_bits(number):
24
if number:
25
bits = []
26
while number:
27
number, remainder = divmod(number, 2)
28
bits.insert(0, remainder)
29
return bits
30
else:
31
return [0]
32
33
# Context manager usage - trace code block
34
def analyze_data():
35
data = [1, 2, 3, 4, 5]
36
37
with pysnooper.snoop():
38
minimum = min(data)
39
maximum = max(data)
40
average = sum(data) / len(data)
41
42
return minimum, maximum, average
43
44
# Output redirection to file
45
@pysnooper.snoop('/tmp/debug.log')
46
def process_data(items):
47
result = []
48
for item in items:
49
result.append(item * 2)
50
return result
51
```
52
53
## Capabilities
54
55
### Main Tracing Decorator
56
57
The primary debugging interface that can be used as both a decorator and context manager.
58
59
```python { .api }
60
class snoop:
61
def __init__(
62
self,
63
output=None,
64
watch=(),
65
watch_explode=(),
66
depth=1,
67
prefix='',
68
overwrite=False,
69
thread_info=False,
70
custom_repr=(),
71
max_variable_length=100,
72
normalize=False,
73
relative_time=False,
74
color=True
75
):
76
"""
77
Snoop on function execution, writing detailed logs to output.
78
79
Args:
80
output: Output destination - None (stderr), file path, stream, or callable
81
watch (tuple): Expressions to watch that aren't local variables
82
watch_explode (tuple): Expressions to expand/explode (show attributes/items)
83
depth (int): Tracing depth for nested function calls (default: 1)
84
prefix (str): Prefix string for all snoop output lines
85
overwrite (bool): Whether to overwrite output file (default: False)
86
thread_info (bool): Include thread information in output
87
custom_repr (tuple): Custom representation functions for objects
88
max_variable_length (int): Maximum length for variable representations (default: 100)
89
normalize (bool): Remove machine-specific data (paths, addresses, timestamps)
90
relative_time (bool): Show timestamps relative to start time
91
color (bool): Enable colored output (default: True on Linux/macOS)
92
"""
93
94
def __call__(self, function_or_class):
95
"""Use as decorator on functions or classes."""
96
97
def __enter__(self):
98
"""Use as context manager - enter tracing block."""
99
100
def __exit__(self, exc_type, exc_value, exc_traceback):
101
"""Use as context manager - exit tracing block."""
102
```
103
104
### Variable Helper Classes
105
106
Helper classes for advanced variable watching and expansion.
107
108
```python { .api }
109
class Attrs:
110
def __init__(self, source, exclude=()):
111
"""
112
Watch object attributes.
113
114
Args:
115
source (str): Variable expression to watch
116
exclude (tuple): Attribute names to exclude from watching
117
"""
118
119
class Keys:
120
def __init__(self, source, exclude=()):
121
"""
122
Watch dictionary/mapping keys and values.
123
124
Args:
125
source (str): Variable expression to watch
126
exclude (tuple): Keys to exclude from watching
127
"""
128
129
class Indices:
130
def __init__(self, source, exclude=()):
131
"""
132
Watch sequence indices and values with optional slicing.
133
134
Args:
135
source (str): Variable expression to watch
136
exclude (tuple): Indices to exclude from watching
137
"""
138
139
def __getitem__(self, slice_obj):
140
"""
141
Enable slicing syntax like Indices('list_var')[1:5].
142
143
Args:
144
slice_obj (slice): Slice object for limiting indices
145
146
Returns:
147
Indices: New Indices instance with slice applied
148
"""
149
150
class Exploding:
151
def __init__(self, source, exclude=()):
152
"""
153
Smart variable expander - automatically determines expansion method.
154
155
Args:
156
source (str): Variable expression to watch
157
exclude (tuple): Items to exclude from watching
158
159
Behavior:
160
- Uses Keys for mappings (dict-like objects)
161
- Uses Indices for sequences (list-like objects)
162
- Uses Attrs for other objects
163
"""
164
```
165
166
### Module Metadata
167
168
Version information for the package.
169
170
```python { .api }
171
__version__: str
172
# Version string (e.g., '1.2.3')
173
174
__version_info__: NamedTuple
175
# Structured version information with major, minor, micro fields
176
```
177
178
## Usage Examples
179
180
### File Output
181
182
Redirect tracing output to a file:
183
184
```python
185
@pysnooper.snoop('/my/log/file.log')
186
def process_data(data):
187
return [x * 2 for x in data]
188
```
189
190
### Watching Expressions
191
192
Monitor specific expressions that aren't local variables:
193
194
```python
195
@pysnooper.snoop(watch=('len(data)', 'data[0]', 'self.status'))
196
def analyze_list(self, data):
197
# Will show values of watched expressions
198
result = sum(data)
199
return result
200
```
201
202
### Variable Expansion
203
204
Expand objects to see their attributes or items:
205
206
```python
207
# Automatic expansion
208
@pysnooper.snoop(watch_explode=('obj', 'data_dict'))
209
def process_object(obj, data_dict):
210
return obj.process(data_dict)
211
212
# Specific expansion types
213
@pysnooper.snoop(watch=(
214
pysnooper.Attrs('obj'), # Object attributes
215
pysnooper.Keys('data_dict'), # Dictionary keys/values
216
pysnooper.Indices('items')[2:5], # List items with slicing
217
))
218
def detailed_processing(obj, data_dict, items):
219
return obj.transform(data_dict, items)
220
```
221
222
### Deep Tracing
223
224
Show snoop lines for functions called within traced functions:
225
226
```python
227
@pysnooper.snoop(depth=2)
228
def main_function():
229
helper_function() # This will also be traced
230
return "done"
231
232
def helper_function():
233
x = 42
234
return x * 2
235
```
236
237
### Multi-threading Support
238
239
Identify threads in multi-threaded applications:
240
241
```python
242
@pysnooper.snoop(thread_info=True)
243
def worker_function(task_id):
244
# Output will include thread information
245
return process_task(task_id)
246
```
247
248
### Custom Output Formatting
249
250
Customize how values are displayed:
251
252
```python
253
def custom_list_repr(obj):
254
if isinstance(obj, list) and len(obj) > 10:
255
return f'list(len={len(obj)})'
256
return repr(obj)
257
258
@pysnooper.snoop(
259
custom_repr=((lambda x: isinstance(x, list), custom_list_repr),),
260
max_variable_length=200,
261
prefix='DEBUG: ',
262
color=False
263
)
264
def process_large_data(big_list):
265
return sum(big_list)
266
```
267
268
### Class Decoration
269
270
Trace all methods in a class:
271
272
```python
273
@pysnooper.snoop()
274
class DataProcessor:
275
def __init__(self, data):
276
self.data = data
277
278
def process(self):
279
return [x * 2 for x in self.data]
280
281
def analyze(self):
282
return sum(self.data)
283
```
284
285
## Environment Variables
286
287
### PYSNOOPER_DISABLED
288
289
Disable all PySnooper tracing globally:
290
291
```bash
292
export PYSNOOPER_DISABLED=1
293
```
294
295
When set, all `@pysnooper.snoop()` decorators and context managers become no-ops.
296
297
## Error Handling
298
299
PySnooper is designed to be non-intrusive. If tracing encounters errors:
300
301
- Variable evaluation failures are silently ignored
302
- File output errors fall back to stderr
303
- Internal exceptions don't interrupt program execution
304
305
The traced code continues running normally even if tracing fails.
306
307
## Advanced Features
308
309
### Generator Support
310
311
PySnooper automatically detects and properly handles generator functions:
312
313
```python
314
@pysnooper.snoop()
315
def fibonacci_generator(n):
316
a, b = 0, 1
317
for _ in range(n):
318
yield a
319
a, b = b, a + b
320
```
321
322
### Lambda and Inline Function Support
323
324
Works with lambda functions and dynamically created functions:
325
326
```python
327
# Trace lambda execution
328
traced_lambda = pysnooper.snoop()(lambda x: x * 2)
329
result = traced_lambda(5)
330
```
331
332
### Context Manager Timing
333
334
Context manager usage shows elapsed time for code blocks:
335
336
```python
337
def analyze_performance():
338
data = list(range(1000))
339
340
with pysnooper.snoop():
341
# This block will show execution time
342
result = sum(x * x for x in data)
343
344
return result
345
```