2010-09-20 6 views
6

Y at-il un mécanisme similaire en Python, l'effet sur set -x a bash?Python peut être fait pour générer le traçage similaire à bash de set -x?

Voici quelques exemple de sortie bash dans ce mode:

 
+ 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 

Je suis au courant du module Python trace, mais sa sortie semble être extrêmement bavard, et non de haut niveau comme celui de bash.

Répondre

7

Peut-être utiliser sys.settrace:

Utilisez traceit() pour activer le traçage, utilisez traceit(False) pour désactiver le suivi.

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) 

cède

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

de Nice! Je n'ai jamais vu ça! – daitangio

+0

Hé bien, je vais l'essayer sous peu. –

0

Vous devriez essayer d'instrument, le module de trace pour obtenir un niveau de détail plus élevé. De quoi avez-vous besoin exactement?

1

Pour tracer des appels spécifiques, vous pouvez envelopper chaque fonction intéressante avec votre propre enregistreur. Cela conduit à des arguments étendus à leurs valeurs plutôt que seulement des noms d'arguments dans la sortie.

fonctions doivent être transmises en tant que chaînes pour éviter les problèmes où les modules redirigent vers d'autres modules, comme os.path/posixpath. Je ne pense pas que vous pouvez extraire le bon nom de module à corriger à partir de l'objet fonction.

Code d'emballage:

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

Utilisation:

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,), {}) 
Questions connexes