2015-09-15 13 views
7

Chciałbym zdefiniować funkcję dziennika, która jest wywoływana z komunikatem, po którym następuje jedna lub więcej zmiennych do wydrukowania. Tak, coś jak poniżej:Jak wydrukować zmienne argumenty o nazwach z poprzedniego stosu?

log("Oh no, error.", x, d) 

dziennika będzie zdefiniowany coś w stylu:

def log(msg, *arg): 
    # Loop through arg, printing caller's variable's name and value. 

Byłoby to log do pliku następujące:

Oh no, error. 
    x = 5 
    d = { foo: "Foo", goo: "Goo" } 

Można to zrobić w ogóle ? Mogę wydrukować locals i argumenty używając inspect, ale nie wiem, czy mogę iterować przez wartości w bieżącej ramce, używając nazw zmiennych poprzedniej ramki. (locals w inspect.getargvalues(previousFrame) ma nazwy, ale wiele innych nazw zbyt.)

+1

W jaki sposób jednoznacznie określasz nazwy zmiennych? Co jeśli osoba dzwoniąca ma "y" w przestrzeni nazw, a jej wartością jest także '5'? Co jeśli dzwoniący przekazuje coś w rodzaju 'd ['foo']'? Czy musisz arbitralnie recurse głęboko w obiektach w obszarze nazw rozmówcy? Co jeśli przekażą wynik wywołania funkcji? 'log ('message', x.bar())'? Istnieje wiele przypadków, które są dość trudne do rozwiązania tutaj, chociaż prawdopodobnie możesz sprawdzić stos i wydrukować _wszystkie zmienne lokalne dzwoniącego. – mgilson

+0

* westchnienie * Tak, myślę, że masz rację mgilson. Więc co powinienem zrobić? Czy muszę usunąć ten wpis? A może to moje myślenie życzeniowe, po prostu chcę funkcji logującej logi zmiennych, które ja daję. Tego w ogóle nie można zrobić? Tak więc, jeśli przekażą 5, wypisuje 5 = 5, jeśli przekażą y, drukuje y = 5. Jeśli przekażą obiekt, wypisuje obiekt = str (obiekt). – Bitdiot

+0

@Bitdiot, dlaczego? Nie jest źle napisane lub źle zorganizowane. I dla mnie osobiście pytanie jest interesujące – ForceBru

Odpowiedz

4

myślę, że można użyć czegoś takiego:

definition

def log(msg, **kwargs): 
    print(msg) 
    for key, value in kwargs.items(): 
     print('{0} = {1}'.format(key,value)) 

definicja (jeżeli zamówienie jest koniecznością)

def log(msg, **kwargs): 
    print(msg) 
    for key, value in sorted(kwargs.items()): 
     print('{0} = {1}'.format(key,value)) 

wykorzystanie

msg='Oh no, error' 
log(msg, x=5, y=6) 

wyjście

Oh no, error 
y = 6 
x = 5 
+2

To jest dobre, ponieważ nie wykorzystuje żadnej czarnej magii. Również [explicite is better than implicit] (https://www.python.org/dev/peps/pep-0020/). –

+2

Należy zauważyć, że kolejność argumentów niekoniecznie jest tym, czego oczekujesz ... http://stackoverflow.com/questions/8977594/in-python-what-determines-the-order-whi--terating-through-kwargs –

+0

Masz rację, nie brałem tutaj pod uwagę porządku, powinienem był wskazać na fakt, że słowniki są nieuporządkowane. Edytowałem odpowiedź. – jlnabais

1

To może być bardzo brudne i nie może pracować od czasu do czasu (robi to na moim komputerze), ale wydaje się, rade.

Co więcej, nie trzeba wszystkich tych sztuczek **keargs. Po prostu zadzwoń pod numer log('Message',as,many,args,as,you,want) i to wszystko.

import inspect, gc 

def log(msg,*args): 
    #This gets the source code line that has to do with args 
    #I mean, that calls log 
    code=''.join(inspect.getframeinfo(gc.get_referrers(args)[0].f_back).code_context).strip() 
    #get the arguments (except msg) 
    c=code.split('log')[1].strip() 
    c=c.replace('(','').replace(')','') 
    c=c.split(',')[1:] 
    if c[-1].endswith(';'): 
     c[-1]=c[-1].replace(';','') 

    for x in xrange(0,len(c)): 
     print c[x],'=',args[x] 


a=5; b='hello' 

print 'test' 

log('hello',a,b); 

print 'hello' 

Nawet jeśli log prowadzony jest od innej funkcji, to jest OK.

+0

Próbowałem tego. Naprawdę fajnie wyglądający kod, ale jeśli dziennik jest nad wieloma liniami, wydaje się, że się potknął.Ciągle mi się podoba, ale myślę, że skłaniam się ku rozwiązaniu key = val. – Bitdiot

Powiązane problemy