PySnooper: Debugging Made Easy, No More Print Statements!🖨️

Manoj Das
5 min readAug 17, 2023

--

What is PySnooper? How to make debugging easy in Python using PySnooper.

Photo by Nubelson Fernandes on Unsplash

PySnooper is a poor man’s debugger. That’s it!

PySnooper is a Python debugging and logging tool designed to help developers track and understand the flow of their code during execution. It allows you to insert “snoop” statements into your code, which will print out variable values, function calls, and other information as your program runs. This can be extremely useful for debugging and gaining insights into how your code behaves.

PySnooper provides a convenient way to trace the execution of your code without having to manually insert print statements or breakpoints at various points in your codebase. It helps you quickly identify issues, understand control flow, and inspect the state of variables at different stages of execution.

History

PySnooper is developed by Ram Rachum. It was created to simplify the debugging process by providing a more intuitive way to trace and monitor the execution of code. PySnooper was designed to be easy to use and to provide detailed insights into variable values, function calls, and control flow during program execution.

The development of PySnooper seems to have gained traction around 2018, and it quickly gained popularity in the Python community due to its simplicity and effectiveness in aiding debugging tasks. Developers found it to be a helpful tool for identifying bugs, understanding how their code behaves, and gaining insights into complex execution paths.

PySnooper’s development continued with updates and improvements, and it became a notable addition to the Python developer’s toolbox. It’s worth noting that PySnooper was not the first tool of its kind, as there were already existing debugging and tracing tools available for Python. However, PySnooper’s focus on simplicity and ease of use contributed to its widespread adoption.

Imagine

You’re trying to figure out why your Python code isn’t doing what you think it should be doing. You’d love to use a full-fledged debugger with breakpoints and watches, but you can’t be bothered to set one up right now.

You want to know which lines are running and which aren’t, and what the values of the local variables are.

Most people would use print lines, in strategic locations, some of them showing the values of variables.

PySnooper lets you do the same, except instead of carefully crafting the right print lines, you just add one decorator line to the function you're interested in. You'll get a play-by-play log of your function, including which lines ran and when, and exactly when local variables were changed.

What makes PySnooper stand out from all other code intelligence tools? You can use it in your shitty, sprawling enterprise codebase without having to do any setup. Just slap the decorator on, as shown below, and redirect the output to a dedicated log file by specifying its path as the first argument.

Example

We’re writing a function that converts a number to binary, by returning a list of bits. Let’s snoop on it by adding the @pysnooper.snoop() decorator:

import pysnooper
@pysnooper.snoop()
def number_to_bits(number):
if number:
bits = []
while number:
number, remainder = divmod(number, 2)
bits.insert(0, remainder)
return bits
else:
return [0]
number_to_bits(6)
Output

Or if you don’t want to trace an entire function, you can wrap the relevant part in a with block:

import pysnooper
import random

def foo():
lst = []
for i in range(10):
lst.append(random.randrange(1, 1000))
with pysnooper.snoop():
lower = min(lst)
upper = max(lst)
mid = (lower + upper) / 2
print(lower, mid, upper)
foo()

which outputs something like:

New var:....... i = 9
New var:....... lst = [681, 267, 74, 832, 284, 678, ...]
09:37:35.881721 line 10 lower = min(lst)
New var:....... lower = 74
09:37:35.882137 line 11 upper = max(lst)
New var:....... upper = 832
09:37:35.882304 line 12 mid = (lower + upper) / 2
74 453.0 832
New var:....... mid = 453.0
09:37:35.882486 line 13 print(lower, mid, upper)
Elapsed time: 00:00:00.000344
Photo by Arnold Francisca on Unsplash

Advantages

Easy Debugging: PySnooper replaces the need for scattered print statements. With a simple decorator, you gain insight into variable values and function calls as your code runs.

Readable Logs: PySnooper generates clear, structured logs that display relevant information in a human-readable format. This helps you quickly identify issues and understand code behavior.

No Code Alteration: Unlike traditional debugging methods, PySnooper doesn’t require you to modify your code. You can add debugging points without cluttering your source code.

Efficient Troubleshooting: PySnooper helps pinpoint problems by showing exactly what happened before an error occurred, enabling efficient troubleshooting.

Control Flow Visualization: You can visualize the execution path and control flow of your code, making it easier to track how different components interact.

Conditional Snoop: PySnooper allows you to specify conditions under which to activate debugging, helping you focus on relevant scenarios.

Function Insights: PySnooper logs function inputs and outputs, aiding comprehension of complex functions and their interactions.

Contextual Information: Logs include file names, line numbers, and module names, giving you context for every logged event.

Interactive Debugging: PySnooper’s interactive mode lets you inspect variables and perform actions directly from the debugging log.

Educational Tool: PySnooper helps developers learn code behavior, making it a useful educational tool for newcomers and experienced programmers alike.

Limitations

Performance Overhead: PySnooper adds some performance overhead to your code, as it logs and captures execution details. This may impact the speed of your program, especially in performance-critical applications.

Complex Logs: In cases of extensive code execution or large datasets, the logs generated by PySnooper can become overwhelming and difficult to navigate, potentially hindering the debugging process.

Code Interference: Although PySnooper aims to minimize code alteration, the addition of snoop statements can still impact the overall structure and readability of your code, especially if used excessively.

Dependency on Libraries: If PySnooper is used in projects that need to be distributed or run on systems where installing additional libraries is a concern, it might introduce dependencies that need to be managed.

Limited Use Cases: While PySnooper is useful for understanding code flow and diagnosing bugs, it might not be the best tool for every debugging scenario, such as low-level memory debugging or specific performance optimizations.

Learning Curve: While PySnooper is designed to be user-friendly, there may still be a learning curve for newcomers to understand its features, options, and how to effectively interpret the generated logs.

Compatibility: PySnooper’s compatibility with all Python environments, versions, and third-party libraries cannot be guaranteed, potentially leading to unexpected behavior or issues.

Potential Overuse: Over-relying on PySnooper for debugging might lead to a lack of traditional debugging skills and understanding of standard debugging tools.

Debugging in Production: While PySnooper is primarily intended for development environments, accidentally leaving snoop statements in production code could expose sensitive information or impact performance.

Lack of Real-time Monitoring: PySnooper provides logging after the fact, which means it might not be suitable for real-time monitoring and debugging of live systems.

— — —

Why do programmers always mix up Christmas and Halloween?

Because Oct 31 == Dec 25!

🙂🙂🙂

--

--