2010-09-20 8 views
6

¿Hay un mecanismo similar en Python, con el efecto set -x tiene en bash?¿Se puede hacer que Python genere un seguimiento similar al conjunto de bash -x?

He aquí algunos ejemplo del resultado de fiesta en este 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 

Soy consciente del módulo de Python trace, sin embargo su salida parece ser muy detallado, y no de alto nivel como la de bash.

Respuesta

7

Tal vez utilice sys.settrace:

Uso traceit() para activar el rastreo, utilice traceit(False) desactivar el seguimiento.

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) 

produce

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

Nice! ¡Nunca había visto esto! – daitangio

+0

Hola, lo intentaré en breve. –

0

Debe intentar instrumentar el módulo de rastreo para obtener un mayor nivel de detalle. ¿Qué necesitas exactamente?

1

Para rastrear las llamadas específicas, se puede envolver cada función interesante con su propio registrador. Esto conduce a argumentos expandidos a sus valores en lugar de solo nombres de argumentos en el resultado.

Las funciones se deben pasar como cadenas para evitar problemas donde los módulos se redirigen a otros módulos, como os.path/posixpath. No creo que pueda extraer el nombre del módulo correcto para el parche solo del objeto de función. código

de embalaje:

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)) 

Uso:

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,), {}) 
Cuestiones relacionadas