2015-09-15 22 views
7

Vorrei definire una funzione di registro chiamata con un messaggio seguito da una o più variabili da stampare. Quindi, qualcosa di simile al seguente:Come stampare gli argomenti variabili con i nomi dello stack precedente?

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

registro sarebbe definito sorta come:

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

Questo sarebbe accedere a un file seguente:

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

si può fare a tutti ? Posso stampare locals e argomenti usando inspect, ma non so se posso scorrere i valori nel frame corrente, usando i nomi delle variabili di un frame precedente. (locals in inspect.getargvalues(previousFrame) ha i nomi, ma un sacco di altri nomi troppo.)

+1

Come si determinano in modo univoco i nomi delle variabili? Cosa accadrebbe se il chiamante avesse 'y' nel namespace e il suo valore fosse anche' 5'? Cosa succede se il chiamante passa qualcosa come 'd ['foo']'? Hai bisogno di ricorrere arbitrariamente in profondità negli oggetti nel namespace del chiamante? Cosa succede se passano il risultato di una chiamata di funzione? 'log ('message', x.bar())'? Ci sono molti casi che sono difficili da risolvere qui ... anche se probabilmente potresti ispezionare lo stack e stampare tutte le variabili locali del chiamante. – mgilson

+0

* sigh * Sì, penso che tu abbia ragione mgilson. Quindi cosa dovrei fare? Devo cancellare questo post? O forse è il mio pio desiderio, voglio solo una funzione di registro che registri le variabili che gli ho dato. Questo non può essere fatto affatto? Quindi, se lo passano 5, stampa 5 = 5. se lo passano y, stampa y = 5. Se passano un oggetto, stampa object = str (oggetto). – Bitdiot

+0

@Bitdiot, perché? Non è scritto male o organizzato male. E per me personalmente la domanda è interessante – ForceBru

risposta

4

penso che si può usare qualcosa di simile:

definizione

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

definizione (se l'ordine è d'obbligo)

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

utilizzo

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

uscita

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

Questo è buono, dal momento che non utilizza alcuna magia nera. Anche [esplicito è meglio di implicito] (https://www.python.org/dev/peps/pep-0020/). –

+2

Nota che l'ordine degli argomenti non è necessariamente quello che ti aspetti ... http://stackoverflow.com/questions/8977594/in-python-what-determines-the-order-while-iterating-through-kwargs –

+0

Hai ragione, non ho preso in considerazione l'ordine qui, avrei dovuto indicare il fatto che i dizionari non sono ordinati. Ho modificato la risposta. – jlnabais

1

che potrebbe essere molto sporca e non può funzionare di volta in volta (lo fa sulla mia macchina), ma sembra fare il trucco.

Inoltre, non ha bisogno di tutti questi trucchi **keargs. Basta chiamare lo log('Message',as,many,args,as,you,want) e basta.

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' 

Anche se log viene eseguito da un'altra funzione, è ok.

+0

Ho provato questo. Codice dall'aspetto davvero elegante, ma se il registro è su più righe, sembra che si verifichi un errore.Mi piace ancora, ma penso di essermi appoggiato alla soluzione key = val. – Bitdiot