What is PDB in Python

Debugging, Logging and Testing¶

The following section introduces methods that you can use to find, fix, and avoid problems.

- The Python debugger¶

A debugger is used to run a buggy program step-by-step to quickly locate the bug; it can also be used to make it easier to understand how an unknown program works by seeing which functions are called up one after the other in the course of the program.

The Python debugger pdb can be called in a shell as follows:

After the call, the input prompt appears. The following instructions, among others, can be entered here:

  • (or short: ):

    With an overview of the most important functions of is displayed.

  • (or short: ):

    The current line is executed with; however, the debugger stops at the next possible point (for example a new function call).

  • and :

    With the specified expression is evaluated and the result is displayed; for example, indicates the value of the specified variable at the current point in time in the program. With the result is output in "pretty print" form.

  • (or short: ):

    The code area in which you are currently in the program when debugging is output with. By default (and usually completely sufficient), eleven lines of code are output, with the current line of code in the middle and marked with.

  • (or short: ):

    With the program is continued until the end of the current function.

  • (or short: ):

    If called without any further argument, all current breakpoints and their consecutive number are output. These can also be set manually using:

    • If an integer number is called as an argument, a breakpoint is set at this point in the source code of the program; that is, the debugger stops when this point is reached.
    • If a function name is called as an argument, a breakpoint is set for this function, that is, the debugger stops every time this function is called.
  • (or short: ):

    The breakpoint with the specified number can be deleted again with.

  • (or short: ):

    With the program is continued until the end, unless a breakpoint set with is reached.

  • respectively:

    With or the program to be debugged is restarted. If the program has been changed since it was last called, it will be reloaded; Breakpoints are retained.

  • respectively:

    The debugger is terminated with or.

In addition, Python statements can also be executed in the debugger; to do this, the respective input line only needs to be started with an exclamation mark ().

Another, often even better use variant is not to call the debugger directly, but to start it from a certain point in the program. You can do this as follows:

importpdb # ... other Python code ... # start debugging from here: pdb.set_trace () # ... other Python code ...

After importing the module, you can start the debugger at any point, even within a function. In this mode of use, the input prompt appears, where the above instructions can be used; debugging then only begins at the "exciting" point.

- Working with log files¶

Log files can be used just like a debugger to find errors in a program. For this purpose, instructions are used in the source code of the program that are very similar to simple instructions. The output is usually not written on the screen, but in a log file with standard formatting. [1]

In Python, logging can easily be done with the help of the logging Module can be implemented. For example, you can activate logging in an interactive interpreter session as follows:

importlogging # Define basic settings: logging.basicConfig (level = logging.INFO) # Create logger for the current session: logger = logging.getLogger (__ name __) # Generate logger message: logger.info ("Let's go!") # Result : INFO: __ main __: Let's go!

The specification of the log level determines how urgent a message is. The following values ​​are defined in the module:

CRITICAL50
ERROR40
WARNING30
INFO20
DEBUG10
NOTSET0

The individual levels can be used directly with,, etc. Such messages are always output when their urgency value is above the level specified in the basic setting.

Most loggers are not used in interactive interpreter sessions, but rather within source code files in conjunction with a log file. The basic configuration can look like this, for example:

importloggingimportmodul1importmodul2 # Define basic settings: logging.basicConfig (filename = 'log.txt', format = '% (levelname) s:% (message) s', level = logging.DEBUG) # Generate logger message: logger.info ("Here we go!")

In this case, a log file and a standard format were also specified when defining the basic settings. If the program is called, the following entry is created in the specified log file:

If the above configuration is made in the basic file of a program that serves as an anchor point for further modules, the instruction at the beginning of the respective file is sufficient within these modules to also write entries in the log file of the basic program within the module to be able to.

Since variable values ​​can also be output by means of log messages, just as with print (), the use of log files can even replace a debugger in many cases.

- Testing using docstrings¶

At the beginning of each function block, a short docstring should be written using triple quotation marks, which contains a brief description of the function. Such a docstring can also contain a short code example of how the function is used and what result the function delivers.

defpower (base, n): "" "Calculate the nth power of the base value. >>> power (5, 3) 125: param base: base value (int or float): param n: exponent (int or float ): returns: Power value (int or float) "" "returnbase ** n

When writing doctests, lines that are normally entered directly in the Python interpreter are introduced; in the following line you can then enter the result that is expected when the previous line is called. If an actual result does not match the expected result when running through the doctest, the respective test fails and a corresponding error message is displayed.

Writing docstrings designed in this way makes code more comprehensible on the one hand; on the other hand, the integrated code examples also test the respective functions. To do this, the doctest package must be imported. The following syntax can be used for a module that only contains auxiliary functions (i.e. usually only imported, but not executed:

if__name __ == "__ main __": importdoctestdoctest.testmod (verbose = 1)

If these lines are written at the end of the module to be tested, you can then call up to activate the tests; however, if the module is only imported, the code section is ignored.

Alternatively, doctests can also be activated directly by calling the interpreter:

python3 -m doctest modulename.py -v

The module is loaded using the interpreter option, and detailed output information is displayed using the (“verbose”) option.

Doctests are only suitable for relatively simple tests in which only a small number of tests per function are carried out and no extensive preparation of the operational environment is necessary; this would make the docstrings too extensive and the code files too confusing. Unit tests offer a better alternative at this point.

- Automated testing¶

When writing unit tests with the help of the unittest package, a corresponding test module is added to each module, with the help of which the functions contained in the main module can be tested. All of these so-called unit tests should be independent of one another.

Since some functions or modules require a certain environment in normal operation, for example an active web server, a database, or an open sample file, the functions and such environments can be provided within the test modules; these two functions are called with every test and create or clean up the required environment.

A test functions of a unit test file always start with, followed by the name of the function to be tested. In order to test classes, classes are also defined in the unit test file, the names of which are made up of the character string and the actual class name. These classes have as the base class.

A unit test class can therefore have the following structure:

importunittestfromodulnameimportK KlassenNameclassTest_K KlassenName (unittest.TestCase): defsetUp (self): passdeftest_functionname1 (self): ... deftest_functionname2 (self): ...... deftearDown (self): pass

The individual test functions always contain - in addition to possible variable definitions or function calls - so-called assertions, ie "assertions" or "hypotheses". It is checked in each case whether the actual result of an instruction matches the expected result. If this is the case, the test is considered passed, otherwise a is triggered.

In Python there are several possible statements, depending on the type of hypothesis:

  • You can use to check whether the return value of the specified function matches the expected result.
  • With numerical evaluations, you can check whether the return value of the specified function agrees with the expected result apart from rounding inaccuracies.

To start unit tests, the following lines can be added to the test file at the end:

if__name __ == '__ main __': unittest.main ()

If you then enter, the function runs through all tests contained in the file. The result then shows how many tests have been successfully completed and where errors may have occurred.

Test automation with

The program simplifies the calling of unit tests, as it automatically calls all test functions that it finds in the current directory including all subdirectories; a test function only has to contain the character string in its function name.

To find and activate tests using, it is sufficient to switch to the test directory in a shell and enter the following line:

When using, there is no need to write test suits. If it is called, the Python debugger is started automatically if an error occurs.


Remarks: