Soru Python: Bir değişkenin adını ve değerini yazdırmak?


Hata ayıklama yaparken, genellikle aşağıdaki gibi baskı ifadelerini görürüz:

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

Bir değişkenin değişkenini veya ismini alacak ve ismini ve değerini yazacak bir işlevi nasıl yazabilirim? Sadece hata ayıklama çıktısı ile ilgileniyorum, bu üretim koduna dahil edilmeyecek.

debugPrint(x)    #  or
debugPrint('x')
x=12

17
2017-08-14 01:22


Menşei


print ("%s=%s" % (name, eval(name))) (Yuck)? - Blorgbeard
olası kopyası Python'da bir değişken adını nasıl yazdırabilirsiniz? - Andy♦
Bunu yapma! Bir hata ayıklayıcı kullanın! :) - jme
Belki de stackoverflow.com/questions/633127/... - Blorgbeard
Ne yazık ki, programlarımı ekranlı bilgisayarlarda çalıştırmıyorum, bu yüzden kayıt benim tek başvurum! - Mark Harrison


Cevaplar:


Sadece kullanabilirsiniz eval:

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

Veya daha genel olarak (aslında çağrı işlevi bağlamında çalışır ve üzerinde durmaz) debug('variable')ama sadece CPython'da):

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)))

Ve yapabilirsin:

>>> x = 1
>>> debug('x + 1')
x + 1 = 2

8
2017-08-14 01:36



Neden düşüşler? Eğer güvenliği ile ilgili ise evalNeden bir sorun olduğunu göremiyorum çünkü bu asla üretim kodunda olmayacak. - Eli Rose
çok basit ve çalışan bir çözüm, tam ihtiyacım olan şey - Oleg


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))

Bu, python'un tüm sürümleri için çalışmaz:

inspect.currentframe ()

CPython uygulama detayı:  Bu işlev, Python'un tüm uygulamalarında mevcut olduğu garanti edilmeyen yorumlayıcıdaki Python yığın çerçeve desteğine dayanır. Python yığın çerçevesi desteği olmadan bir uygulamada çalıştırılıyorsa, bu işlev Hiçbiri döndürmez.


2
2017-08-14 01:58





Oldukça çirkin, ama işi yapar:

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
2017-08-14 01:54





Bir şeyleri yazabilmek için aşağıdakileri yazdım (dosya 41'inde) describe.py):

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

ve bakın:

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)]

İşte nasıl:

# 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


0
2018-03-29 13:38