2010-09-20 3 views
6

C'è un meccanismo simile in Python, per l'effetto set -x ha su bash?Si può fare in modo che Python generi una traccia simile al set -x di bash?

Ecco qualche esempio di output da bash in questo modo:

 
+ for src in cpfs.c log.c popcnt.c ssse3_popcount.c blkcache.c context.c types.c device.c 
++ my_mktemp blkcache.c.o 
+++ mktemp -t blkcache.c.o.2160.XXX 
++ p=/tmp/blkcache.c.o.2160.IKA 
++ test 0 -eq 0 
++ echo /tmp/blkcache.c.o.2160.IKA 
+ obj=/tmp/blkcache.c.o.2160.IKA 

Sono consapevole del modulo Python trace, tuttavia la sua uscita sembra essere estremamente prolisso, e non di alto livello come quello di bash.

risposta

7

Forse usano sys.settrace:

Usa traceit() per attivare la traccia, utilizzare traceit(False) per disattivare l'analisi.

import sys 
import linecache 

def _traceit(frame, event, arg): 
    ''' 
    http://www.dalkescientific.com/writings/diary/archive/2005/04/20/tracing_python_code.html 
    ''' 
    if event == "line": 
     lineno = frame.f_lineno 
     filename = frame.f_globals["__file__"] 
     if (filename.endswith(".pyc") or 
      filename.endswith(".pyo")): 
      filename = filename[:-1] 
     name = frame.f_globals["__name__"] 
     line = linecache.getline(filename, lineno) 
     print "%s # %s:%s" % (line.rstrip(), name, lineno,) 
    return _traceit 

def _passit(frame, event, arg): 
    return _passit 

def traceit(on=True): 
    if on: sys.settrace(_traceit) 
    else: sys.settrace(_passit) 

def mktemp(src): 
    pass 

def my_mktemp(src): 
    mktemp(src) 
    p=src 

traceit() 
for src in ('cpfs.c','log.c',): 
    my_mktemp(src) 
traceit(False) 

cede

mktemp(src) # __main__:33 
pass # __main__:30 
p=src # __main__:34 
mktemp(src) # __main__:33 
pass # __main__:30 
p=src # __main__:34 
if on: sys.settrace(_traceit) # __main__:26 
else: sys.settrace(_passit) # __main__:27 
+0

Nizza! Non ho mai visto questa roba! – daitangio

+0

Ehi, bene, ci proverò presto. –

0

Si dovrebbe provare a strumentare il modulo di traccia per ottenere un livello di dettaglio più alto. Cosa ti serve esattamente?

1

Per tracciare chiamate specifiche, si può avvolgere ogni funzione interessante con il proprio registratore. Questo porta a argomenti ampliati ai loro valori piuttosto che solo nomi di argomenti nell'output.

Le funzioni devono essere passate come stringhe per prevenire problemi di reindirizzamento dei moduli ad altri moduli, come os.path/posixpath. Non penso che tu possa estrarre il nome del modulo giusto per la patch solo dall'oggetto funzione. Codice

Confezione:

import importlib 

def wrapper(ffull, f): 
    def logger(*args, **kwargs): 
     print "TRACE: %s (%s, %s)" % (ffull, args, kwargs) 
     return f(*args, **kwargs) 
    return logger 

def log_execution(ffull): 
    parts = ffull.split('.') 
    mname = '.'.join(parts[:-1]) 
    fname = parts[-1] 
    m = importlib.import_module(mname) 
    f = getattr(m, fname) 
    setattr(m, fname, wrapper(ffull, f)) 

Usage:

for f in ['os.path.join', 'os.listdir', 'sys.exit']: 
    log_execution(f) 

p = os.path.join('/usr', 'bin') 
os.listdir(p) 
sys.exit(0) 

.... 

% ./a.py 
TRACE: os.path.join (('/usr', 'bin'), {}) 
TRACE: os.listdir (('/usr/bin',), {}) 
TRACE: sys.exit ((0,), {})