Python能否生成类似于bash的set -x的追踪信息?
在Python中,有没有类似于bash中set -x
的功能呢?
下面是bash在这种模式下的一些示例输出:
+ 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
我知道Python有一个叫做trace
的模块,不过它的输出似乎非常详细,不像bash那样简洁明了。
3 个回答
0
你可以尝试使用跟踪模块来获取更详细的信息。你具体需要什么呢?
1
为了追踪特定的函数调用,你可以用自己的记录器把每个有意思的函数包裹起来。这样做的结果是,输出中会显示参数的实际值,而不仅仅是参数的名字。
函数需要以字符串的形式传入,这样可以避免一些问题,比如模块之间的重定向,比如 os.path 和 posixpath。我觉得仅仅从函数对象中提取正确的模块名来进行修改是做不到的。
包裹代码的示例:
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))
使用方法:
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,), {})
8
你可以试试使用 sys.settrace 这个功能:
用 traceit()
来开启追踪,使用 traceit(False)
来关闭追踪。
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)
这样会得到
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