Beim Debuggen sehen wir häufig Druckanweisungen wie diese:

print x        # easy to type, but no context
print 'x=',x   # more context, harder to type
12
x= 12

Wie kann eine Funktion geschrieben werden, die eine Variable oder einen Namen einer Variablen verwendet und deren Namen und Wert druckt? Ich bin ausschließlich am Debuggen von Ausgaben interessiert, dies wird nicht in den Produktionscode aufgenommen.

debugPrint(x)    #  or
debugPrint('x')
x=12
79
Mark Harrison 14 Aug. 2015 im 04:22

8 Antworten

Beste Antwort

Sie können einfach eval verwenden:

def debug(variable):
    print variable, '=', repr(eval(variable))

Oder allgemeiner (was tatsächlich im Kontext der aufrufenden Funktion funktioniert und nicht auf debug('variable'), sondern nur auf CPython bricht):

from __future__ import print_function

import sys

def debug(expression):
    frame = sys._getframe(1)

    print(expression, '=', repr(eval(expression, frame.f_globals, frame.f_locals)))

Und Sie können tun:

>>> x = 1
>>> debug('x + 1')
x + 1 = 2
20
Blender 14 Aug. 2015 im 02:27

Ziemlich hässlich, macht aber den Job:

import inspect, re
def getm(p):
  for line in inspect.getframeinfo(inspect.currentframe().f_back)[3]:
    match = re.search(r'\bvarname\s*\(\s*([A-Za-z_][A-Za-z0-9_]*)\s*\)', line)
    if match:
      return match.group(1)
x=21
search = getm(x);
print (search , '=' , eval(search))
0
Mohit Bhasi 14 Aug. 2015 im 01:54
import inspect
import re
def debugPrint(x):
    frame = inspect.currentframe().f_back
    s = inspect.getframeinfo(frame).code_context[0]
    r = re.search(r"\((.*)\)", s).group(1)
    print("{} = {}".format(r,x))

Dies funktioniert nicht für alle Python-Versionen:

inspect.currentframe ()

CPython-Implementierungsdetail: Diese Funktion basiert auf der Unterstützung von Python-Stack-Frames im Interpreter, die nicht in allen Implementierungen von Python garantiert ist. Wenn Sie in einer Implementierung ohne Python-Stack-Frame-Unterstützung ausgeführt werden, gibt diese Funktion None zurück.

3
Padraic Cunningham 14 Aug. 2015 im 02:10

Ich habe gerade eine Funktion wie diese erfunden, die einen beliebigen Ausdruck druckt:

import inspect, pprint

def pp(n):
    print()
    print(n,"=")
    f=inspect.stack()[1].frame
    pprint.pprint(eval(n,f.f_globals,f.f_locals))

(Ich habe eine leere Zeile vor dem Namen und eine neue Zeile vor dem Wert 'verwendet, da ich in meinem Fall große Datenstrukturen drucken musste. Es ist einfacher, eine solche Ausgabe mit den Zeilenumbrüchen zu lesen.)

Es ist sicher, solange Sie keine nicht vertrauenswürdigen Eingaben weitergeben.

Sie könnten auch an meinem dump Modul interessiert sein. Es druckt alle Felder des Objekts in einer für Menschen lesbaren Form. Hat sich als äußerst nützlich für das Debuggen erwiesen.

0
ivan_pozdeev 26 Nov. 2018 im 23:57

Ein einfaches Beispiel wäre:

def debugPrint(*expr):
    text = traceback.extract_stack()[-2][3]
    begin = text.find('debugPrint(') + len('debugPrint(')
    end = text.find(')',begin)
    text=[name.strip() for name in text[begin:end].split(',')]
    for t, e in text, expr:
        print(str(t) +  " = " + str(e))

Ich hoffe es hilft!

0
Sujay Kumar 25 Okt. 2018 im 11:22

Python 3.8-F-String-Syntax =

Es ist angekommen!

#!/usr/bin/env python3
foo = 1
bar = 2
print(f"{foo=} {bar=}")

Ausgabe:

foo=1 bar=2 

Hinzugefügt in Festschreiben Fügen Sie das Debuggen von F-Strings mit '=' hinzu. " welche Dokumente:

f-strings now support =  for quick and easy debugging
-----------------------------------------------------

Add ``=`` specifier to f-strings. ``f'{expr=}'`` expands
to the text of the expression, an equal sign, then the repr of the
evaluated expression.  So::

  x = 3
  print(f'{x*9 + 15=}')

Would print ``x*9 + 15=42``.

Es funktioniert also auch für beliebige Ausdrücke. Nett!

45
Ciro Santilli 新疆改造中心法轮功六四事件 26 Juli 2019 im 19:33

Ich habe Folgendes geschrieben, um so etwas eingeben zu können (in Zeile 41 der Datei describe.py):

describe('foo' + 'bar')
describe(numpy.zeros((2, 4)))

Und sehen:

describe.py@41 describe('foo' + 'bar') = str(foobar) [len=6]   
describe.py@42 describe(numpy.zeros((2, 4))) = ndarray(array([[0., 0., 0., 0.],
   [0., 0., 0., 0.]])) [shape=(2, 4)]

Hier ist wie:

# Print the line and filename, function call, the class, str representation and some other info

# Inspired by https://stackoverflow.com/a/8856387/5353461
import inspect
import re


def describe(arg):
    frame = inspect.currentframe()
    callerframeinfo = inspect.getframeinfo(frame.f_back)
    try:
        context = inspect.getframeinfo(frame.f_back).code_context
        caller_lines = ''.join([line.strip() for line in context])
        m = re.search(r'describe\s*\((.+?)\)$', caller_lines)
        if m:
            caller_lines = m.group(1)
            position = str(callerframeinfo.filename) + "@" + str(callerframeinfo.lineno)

            # Add additional info such as array shape or string length
            additional = ''
            if hasattr(arg, "shape"):
                additional += "[shape={}]".format(arg.shape)
            elif hasattr(arg, "__len__"):  # shape includes length information
                additional += "[len={}]".format(len(arg))

            # Use str() representation if it is printable
            str_arg = str(arg)
            str_arg = str_arg if str_arg.isprintable() else repr(arg)

            print(position, "describe(" + caller_lines + ") = ", end='')
            print(arg.__class__.__name__ + "(" + str_arg + ")", additional)
        else:
            print("Describe: couldn't find caller context")

    finally:
        del frame
        del callerframeinfo

https://gist.github.com/HaleTom/125f0c0b0a1fb4fbf4311e6aa763844b

3
Tom Hale 29 März 2018 im 13:38

Antwort nehmen @Blender Antwort einen Schritt weiter mit mehreren Variablen:

def debug(variables, sep =''):
        vars = variables.split(',')
        for var in vars:
          print(var, '=', repr(eval(var)), end = sep)

Beispiel:

import bumpy as np
gPrimeLinear = lambda z: np.ones(np.array(z).size)*z
gPrimeSigmoid = lambda z: 1./(1+np.exp(-z))*(1-1./(1+np.exp(-z)))
gPrimeTanh = lambda z: 1- np.tanh(z)**2
z = np.array([ 0.2, 0.4, 0.1])
debug("z, gPrimeLinear(z), gPrimeSigmoid(z), gPrimeTanh(z)", '\n')

Dies ergibt:

> z = array([0.2, 0.4, 0.1])  
> gPrimeLinear(z) = array([0.2, 0.4, 0.1]) 
> gPrimeSigmoid(z) = array([0.24751657, 0.24026075, 0.24937604]) 
> gPrimeTanh(z) = array([0.96104298, 0.85563879, 0.99006629])
0
chikitin 15 Nov. 2019 im 14:32