Boost Your Python Debugging with PySnooper: A Complete Guide
Learn how to enhance Python debugging using the PySnooper library, covering quick installation, simple examples, advanced features like output redirection, variable watching, depth control, thread info, custom representations, and remote debugging tips, all illustrated with clear code snippets and screenshots.
For every programmer, debugging is an essential skill.
When code gets stuck or throws errors, different debugging methods suit different scenarios and users:
If you are a beginner, using print or logging is the simplest way.
If you develop locally on Windows or macOS, a graphical IDE debugger is ideal.
If you troubleshoot bugs on a server, using pdb is the preferred choice.
If your project depends on a complex server environment, consider PyCharm's remote debugging.
Beyond these, a very useful debugging tool is PySnooper, which has received over 13k stars on GitHub and is praised by many developers.
1. Quick Installation
Run the following commands to install PySnooper:
$ python3 -m pip install pysnooper<br># or<br>$ conda install -c conda-forge pysnooper<br># or<br>$ yay -S python-pysnooper2. Simple Example
The code below defines a demo_func that creates a profile dictionary, updates it, and returns it. The function itself has no real purpose; it simply demonstrates PySnooper.
import pysnooper
@pysnooper.snoop()
def demo_func():
profile = {}
profile["name"] = "写代码的明哥"
profile["age"] = 27
profile["gender"] = "male"
return profile
def main():
profile = demo_func()
main()Running it from the terminal produces detailed tracing output:
[root@iswbm ~]# python3 demo.py
Source path:... demo.py
17:52:49.624943 call 4 def demo_func():
17:52:49.625124 line 5 profile = {}
New var:....... profile = {}
17:52:49.625156 line 6 profile["name"] = "写代码的明哥"
Modified var:.. profile = {'name': '写代码的明哥'}
17:52:49.625207 line 7 profile["age"] = 27
Modified var:.. profile = {'name': '写代码的明哥', 'age': 27}
17:52:49.625254 line 8 profile["gender"] = "male"
Modified var:.. profile = {'name': '写代码的明哥', 'age': 27, 'gender': 'male'}
17:52:49.625306 line 10 return profile
17:52:49.625344 return 10 return profile
Return value:.. {'name': '写代码的明哥', 'age': 27, 'gender': 'male'}
Elapsed time: 00:00:00.000486From this output you can see that PySnooper records:
The code snippet, line numbers, and timestamps for each line.
How local variable values change, when variables are added or modified.
The function's return value.
The execution time of the function.
To obtain this detailed information, simply add the decorator @pysnooper.snoop() to the function you want to trace.
3. Detailed Usage
2.1 Redirect Output to a Log File
Without parameters, @pysnooper.snoop() prints to standard output. For bugs that require long‑running monitoring, you can redirect the output to a file:
@pysnooper.snoop(output='/var/log/debug.log')
def demo_func():
...2.2 Watch Non‑Local Variables
By default PySnooper tracks only local variables. To watch a global variable, use the watch argument:
out = {"foo": "bar"}
@pysnooper.snoop(watch=('out["foo"]'))
def demo_func():
...When out["foo"] changes, PySnooper will log the new value.
2.3 Set Tracing Depth
If the traced function calls other functions, you can increase the depth to follow those calls:
@pysnooper.snoop(depth=2)
def demo_func():
...2.4 Add a Prefix to Log Entries
When tracing multiple functions, a prefix helps distinguish their logs:
@pysnooper.snoop(output="/var/log/debug.log", prefix="demo_func: ")
def demo_func():
...2.5 Control Maximum Output Length
By default, variable values longer than 100 characters are truncated. You can change this limit:
@pysnooper.snoop(max_variable_length=200)Setting max_variable_length=None disables truncation.
@pysnooper.snoop(max_variable_length=None)2.6 Enable Thread Information
For multithreaded debugging, add thread_info=True to include thread identifiers in the log.
@pysnooper.snoop(thread_info=True)
def demo_func():
...2.7 Custom Object Representation
Use the custom_repr argument to define how specific object types are displayed:
class Person:
pass
def print_person_obj(obj):
return f"<Person {obj.name} {obj.age} {obj.gender}>"
@pysnooper.snoop(custom_repr=(Person, print_person_obj))
def demo_func():
...You can pass a tuple of multiple type‑function pairs, or use a callable that determines the type.
@pysnooper.snoop(custom_repr=((Person, print_person_obj), (numpy.ndarray, print_ndarray)))
def demo_func():
...These advanced options make PySnooper a powerful and flexible debugging tool for Python developers.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Python Crawling & Data Mining
Life's short, I code in Python. This channel shares Python web crawling, data mining, analysis, processing, visualization, automated testing, DevOps, big data, AI, cloud computing, machine learning tools, resources, news, technical articles, tutorial videos and learning materials. Join us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
