Domanda

myapp/foo.py Supponiamo che contiene:

def info(msg):
    caller_name = ????
    print '[%s] %s' % (caller_name, msg)

E myapp/bar.py contiene:

import foo
foo.info('Hello') # => [myapp.bar] Hello

Voglio caller_name da impostare per l'attributo __name__ delle funzioni di chiamata modulo (che è 'myapp.foo') in questo caso. Come si può fare?

È stato utile?

Soluzione

Estrai il modulo ispezionare:

inspect.stack() restituirà le informazioni di stack.

all'interno di una funzione, inspect.stack()[1] tornerà pila del chiamante. Da lì, è possibile ottenere ulteriori informazioni sul nome della funzione del chiamante, moduli, ecc.

Si veda la documentazione per i dettagli:

http://docs.python.org/library/inspect.html

Inoltre, Doug Hellmann ha un interessante resoconto del modulo di ispezionare nella sua serie PyMOTW:

http://pymotw.com/2/inspect/index.html# modulo-ispezionare

EDIT: Ecco un po 'di codice che fa quello che si vuole, credo che:

def info(msg):
    frm = inspect.stack()[1]
    mod = inspect.getmodule(frm[0])
    print '[%s] %s' % (mod.__name__, msg)

Altri suggerimenti

Di fronte a un problema simile, ho trovato che sys._current_frames () dal sys modulo contiene informazioni interessanti che possono aiutare, senza la necessità di importare ispezionare, almeno in specifici casi d'uso .

>>> sys._current_frames()
{4052: <frame object at 0x03200C98>}

È quindi possibile "cambiare" utilizzando f_back:

>>> f = sys._current_frames().values()[0]
>>> # for python3: f = list(sys._current_frames().values())[0]

>>> print f.f_back.f_globals['__file__']
'/base/data/home/apps/apricot/1.6456165165151/caller.py'

>>> print f.f_back.f_globals['__name__']
'__main__'

Per il nome del file è anche possibile usare f.f_back.f_code.co_filename, come suggerito da Mark Roddy sopra. Non sono sicuro dei limiti e delle avvertenze di questo metodo (più thread sarà molto probabilmente un problema), ma ho intenzione di usarlo nel mio caso.

Non consiglio fare questo, ma è possibile raggiungere il tuo obiettivo con il seguente metodo:

def caller_name():
    frame=inspect.currentframe()
    frame=frame.f_back.f_back
    code=frame.f_code
    return code.co_filename

Poi aggiornare il metodo esistente come segue:

def info(msg):
    caller = caller_name()
    print '[%s] %s' % (caller, msg)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top