Debug showing variable name and value?

1

Many times when I need to debug the value of a variable at runtime I use print() .

But when there are many variables, I need to identify the name of the variable along with the value.

In this way print becomes more laborious :

print ("x=", x, "y=", y, "x+y*2=", x+y*2)

The ideal would be a simple command like:

debug (x, y, x+y*2)

... which would automatically add variables as in the print above.

The problem is that I have not seen a way to do this.

Any ideas?

    
asked by anonymous 30.09.2018 / 16:27

4 answers

3

As discussed, an option to display the debug of variables is by using the inspect . Using the inspect.stack function you can check the context from which the function was executed and access local and global variables in this context. So, instead of passing the variable itself to function, you can only pass its name so that the function will be in charge of accessing its value by inspection. For this example I have also used the module tabulate to format the output easily and legibly.

import inspect
import tabulate


def debug(*args):

    # Busca o contexto de quem chamou a função debug:
    context = inspect.stack()[1][0]

    # Obtém detalhes de onde foi executado o debug:
    filename = context.f_code.co_filename
    linenumber = context.f_lineno

    # Resultados a serem exibidos:
    result = []

    # Percorre todas as variáveis a serem exibidas:
    for name in args:
        # Verifica se é uma variável local no contexto:
        if name in context.f_locals:
            result.append([name, context.f_locals[name]])
        # Verifica se é uma variável global no contexto:
        elif name in context.f_globals:
            result.append([name, context.f_globals[name]])
        # Variável não encontrada no contexto:
        else:
            result.append([name, 'Não encontrada'])

    # Exibe os resultados em forma de tabela:
    print(f'[DEBUG] {filename} ({linenumber})')
    print(tabulate.tabulate(result, headers=['Variável', 'Valor']))

An example usage would be:

>>> x, y, nome = 1, 2, 'Anderson Carlos Woss'
>>> debug('x', 'y', 'nome', 'foo')
[DEBUG] python (34)
Variável    Valor
----------  --------------------
x           1
y           2
nome        Anderson Carlos Woss
foo         Não encontrada

See working at Repl.it

Example calling within a function

Doing debug of a local variable and a global variable:

autor = "Anderson Carlos Woss"


def hello(nome):
    debug('nome', 'autor')
    print(f'Olá, {nome} (por {autor})')


hello('John Doe')

See working at Repl.it

The output will be:

[DEBUG] python (37)
Variável    Valor
----------  --------------------
nome        John Doe
autor       Anderson Carlos Woss

Olá, John Doe (por Anderson Carlos Woss)

However, for expression, such as x+y*2 , the function will not work. It is possible to implement the function for this, but I believe it will be impractical. It will be much simpler for you to assign the expression to another variable and pass it to the function. For example:

>>> x, y = 1, 2
>>> x_plus_2y = x + 2*y
>>> debug('x', 'y', 'x_plus_2y')

Displaying:

[DEBUG] python (38)
Variável      Valor
----------  -------
x                 1
y                 2
x_plus_2y         5
    
01.10.2018 / 17:17
7

You can print a dictionary with all local variables if you make print(locals()) .

Also, if you do not know, I recommend learning how to use PDB (Python Debuger) - which allows that you interactively track the execution of the program, and inspect the value of the variables whenever you want. In Python 3.7, just put breakpoint() in the middle of the code. In any previous version, the line import pdb; pdb.set_trace()

    
30.09.2018 / 16:55
0

They are within the module logging :

import logging
from random import randint

logging.basicConfig(level=logging.DEBUG)

logging.info('Iniciando o programa')

for i in range(0, 5):
    x = randint(0, 100)
    y = randint(0, 100)
    z = y if y > 100 else x
    logging.debug('x={}, y={}, z={}'.format(x,y,z))

logging.info('Finalizando o programa')

And the result would look something like this:

INFO:root:Iniciando o programa DEBUG:root:x=68, y=59, z=68 DEBUG:root:x=65, y=38, z=65 DEBUG:root:x=97, y=64, z=97 DEBUG:root:x=15, y=26, z=15 DEBUG:root:x=29, y=13, z=29 INFO:root:Finalizando o programa

Of course, they are sent to STDERR but you can direct them to a file, as well as customize what is displayed in the message and also set the logging level (using level = logging.INFO only the first and last messages would be displayed ) for when knowing the value of the variables is no longer necessary. :-)

    
30.09.2018 / 16:44
0

Using eval is the solution.

Here is my new function debug , which is simple. You just need to put variable names in a list of strings:

 def debug (vars):
     for var in vars:
         print (var, "=", eval (var))

Example:

 t = "algum texto"
 n = 3.1416
 debug (['t', 'n'])

Result:

 t = algum texto
 n = 3.1416
    
01.10.2018 / 02:31