2015-09-15 5 views
7

Ich möchte eine Protokollfunktion definieren, die mit einer Nachricht gefolgt von einer oder mehreren Variablen zum Ausdrucken aufgerufen wird. Also, so etwas wie die folgenden:Wie drucke ich die Variablenargumente mit Namen aus dem vorherigen Stapel?

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

Protokoll definiert werden würde sorta mag:

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

Das in eine Datei die folgende Protokoll würde:

Oh no, error. 
    x = 5 
    d = { foo: "Foo", goo: "Goo" } 
Kann man das überhaupt getan werden ? Ich kann Locals und Argumente mit inspect drucken, aber ich weiß nicht, ob ich Werte im aktuellen Frame durchlaufen kann, indem ich die Variablennamen eines vorherigen Frames verwende. ( locals in inspect.getargvalues(previousFrame) hat die Namen, aber viele andere Namen auch.)

+1

Wie bestimmen Sie die Variablennamen eindeutig? Was wäre, wenn der Aufrufer im Namensraum "y" hätte und sein Wert auch "5" wäre? Was passiert, wenn der Anrufer etwas wie "d ['foo']" übergibt? Müssen Sie beliebig tief in die Objekte im Namespace des Aufrufers recurren? Was ist, wenn sie das Ergebnis eines Funktionsaufrufs übergeben? 'log ('Nachricht', x.bar())'? Es gibt viele Fälle, die hier ziemlich schwer zu lösen sind ... obwohl Sie wahrscheinlich den Stack inspizieren und _all_ der lokalen Variablen des Aufrufers ausdrucken könnten. – mgilson

+0

* seufz * Ja, ich denke du bist richtig mgilson. Also was soll ich tun? Muss ich diesen Beitrag löschen? Oder vielleicht ist es mein Wunschdenken, ich möchte nur eine Protokollfunktion, die die Variablen protokolliert, die ich ihr gebe. Das kann überhaupt nicht gemacht werden? Also, wenn sie 5 übergeben, wird 5 = 5 ausgegeben. Wenn sie an y übergeben werden, wird y = 5 ausgegeben. Wenn sie ein Objekt übergeben, wird Objekt = str (Objekt) ausgegeben. – Bitdiot

+0

@Bitdiot, warum? Es ist nicht schlecht geschrieben oder schlecht organisiert. Und für mich persönlich ist die Frage interessant – ForceBru

Antwort

4

Ich glaube, Sie so etwas wie dieses verwenden können:

Definition

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

Definition (wenn Auftrag ist ein Muss)

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

Nutzung

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

Ausgang

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

Das ist gut, da es keine schwarze Magie verwendet. Auch [explizit ist besser als implizit] (https://www.python.org/dev/peps/pep-0020/). –

+2

Beachten Sie, dass die Reihenfolge der Argumente nicht unbedingt das ist, was Sie erwarten ... http://stackoverflow.com/questions/8977594/in-python-what-determines-the-order-while-iterating-through-kwargs –

+0

Sie haben Recht, ich habe die Bestellung hier nicht berücksichtigt, ich hätte darauf hinweisen müssen, dass Wörterbücher ungeordnet sind. Ich habe die Antwort bearbeitet. – jlnabais

1

Das ist sehr schmutzig sein könnte und möglicherweise nicht von Zeit zu Zeit (es tut dies auf meiner Maschine), aber es scheint, den Trick zu tun.

Darüber hinaus benötigt es nicht alle diese **keargs Tricks. Sie rufen einfach log('Message',as,many,args,as,you,want) und das ist alles.

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' 

Auch wenn log von einer anderen Funktion ausgeführt wird, es ist OK.

+0

Ich habe das versucht. Wirklich gut aussehender Code, aber wenn das Protokoll mehrere Zeilen enthält, scheint es zu stolpern.Ich mag es immer noch, aber ich glaube, ich lehne mich der Schlüssel = val-Lösung zu. – Bitdiot