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
8 Antworten
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
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))
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.
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.
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!
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!
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
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])
Verwandte Fragen
Verknüpfte Fragen
Neue Fragen
python
Python ist eine dynamisch typisierte Mehrzweck-Programmiersprache mit mehreren Paradigmen. Es wurde entwickelt, um schnell zu lernen, zu verstehen, zu verwenden und eine saubere und einheitliche Syntax durchzusetzen. Bitte beachten Sie, dass Python 2 ab dem 01.01.2020 offiziell nicht mehr unterstützt wird. Fügen Sie für versionenspezifische Python-Fragen das Tag [python-2.7] oder [python-3.x] hinzu. Wenn Sie eine Python-Variante (z. B. Jython, PyPy) oder eine Bibliothek (z. B. Pandas und NumPy) verwenden, fügen Sie diese bitte in die Tags ein.