Print is probably the most frequently used function in Python. Many people get their start with Python’s Hello World program. Python’s Hello World program is a one-line program that calls the built-in Print function and prints the string “Hello World” to the console.

Print is usually a heavy user of the function, even Python developers. The biggest use of Print is for debugging Python programs. For example, Print is used to Print the running steps of the program, or Print is used to Print the changes in the value of a variable during the running of the program. Since Python is an interpreted programming language that can be executed without compilation, the addition of Print debugging statements allows developers to execute Python programs immediately and get debugging results.

The advantages of using Print debugging are straightforward and easy to use, but the disadvantages are also obvious: if you want to Print a lot of information, you need to write many lines of Print statements; These statements often need to be deleted one by one after debugging. It’s a tedious process. In a word, the downside of debugging with Print is that it is less efficient.

In addition to the Print function, another common Python program debugging tool is Python’s logging module. The Logging module writes the required information to a log file according to a predefined format. By tracing log files, you can also achieve debugging purposes.

Using logging for debugging looks a little more formal than the Print function. Also, when debugging is complete, the logging statement does not need to be removed and can still function in the production environment. In addition, the logging module allows us to dynamically decide what logs to print by adjusting the log level (INFO/DEBUG/WARN/ERR). On the other hand, the logging module requires tedious Setup before being used, which makes it a bit more difficult and inconvenient to use.

So, is there a better way to debug? Recently, a new third-party library dedicated to debugging Python programs has appeared on Github called PySnooper. A Snooper is a listener. A PySnooper, as the name suggests, is a tool that listens to the execution of Python programs. As soon as PySnooper was introduced, it caused serious concern in the Python community. In only one month, I gained 10K+ STAR, which is really very popular.

Compared with Print debugging, which often requires many lines of Print statements, PySnooper can debug the whole function with only one line of code, which is more efficient. Compared to the Logging module, using PySnooper is simpler and requires no tedious configuration.

Let’s just look at this example.

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)
Copy the code

Execute this code and the output (excerpt) looks like this:

Starting var:.. number = 6
15:29:11.327032 call         4 def number_to_bits(number):
15:29:11.327032 line         5     if number:
15:29:11.327032 line         6         bits = []
New var:....... bits = []
15:29:11.327032 line         7         while number:
15:29:11.327032 line         8             number, remainder = divmod(number, 2)
New var:....... remainder = 0
Modified var:.. number = 3
15:29:11.327032 line         9             bits.insert(0, remainder)
Modified var:.. bits = [0]
Copy the code

As you can see, we can listen on a Python function by importing the PySnooper module and adding the decorator @pysnooper.snoop() to the function.

In the example above, based on the output, we can get:

  • The order in which the steps are executed, such as line 2 of the execution result, tells us that def number_to_bits was executed at 15:29:11.327032.

  • For example, line 9 of the execution result tells us that the value of the local variable number has changed to 3.

PySnooper supports flexible and diverse program debugging, including but not limited to:

  1. Add the decorator @pysnooper.snoop() to the function to listen on it.

  2. Use the with pysnooper.snoop() statement to implement a block, that is, one or more lines of programs to listen.

  3. Use @pysnooper.snoop(‘/my/log/file.log’) to redirect the listening results to the file system.

  4. Listen for values of non-local variables:

    @pysnooper.snoop(variables=('foo.bar','self.whatever'))
    Copy the code
  5. Listen for all elements or attributes of a list or dictionary variable:

    @pysnooper.snoop(watch=('foo.bar','self.x["whatever"]'))
    Copy the code
  6. Deep listening — Listening for other functions called by lines in a function:

    @pysnooper.snoop(depth=2)
    Copy the code
  7. In multithreaded programs, specify which threads to listen on:

    @pysnooper.snoop(thread_info=True)
    Copy the code

For more advanced uses of PySnooper see: github.com/cool-RR/PyS…

In addition, PySnooper installation is very simple:

pip install pysnooper
Copy the code

To sum up, PySnooper is a simple, powerful, and efficient Python debugging tool that combines all the advantages into one. No wonder it has been so quickly embraced by the community.