shell中“set-x”的Python等价物是什么?
请建议使用Python命令,该命令相当于shell脚本中的shell中“set-x”的Python等价物是什么?,python,shell,debugging,Python,Shell,Debugging,请建议使用Python命令,该命令相当于shell脚本中的set-x 有没有办法打印/记录Python执行的每个源文件行?您可以使用以下模块: 上面的命令行将在执行时显示每一行代码。您可以使用该模块: 上面的命令行将在执行时显示每一行代码。要使用跟踪模块获得与bash-x适当等效的代码,需要使用--ignore dir来阻止打印导入的每个模块的源代码行,例如,python-m trace--trace--ignore dir/usr/lib/python2.7--ignore dir/usr/l
set-x
有没有办法打印/记录Python执行的每个源文件行?您可以使用以下模块:
上面的命令行将在执行时显示每一行代码。您可以使用该模块:
上面的命令行将在执行时显示每一行代码。要使用
跟踪
模块获得与bash-x
适当等效的代码,需要使用--ignore dir
来阻止打印导入的每个模块的源代码行,例如,python-m trace--trace--ignore dir/usr/lib/python2.7--ignore dir/usr/lib/pymodules repost.py
,根据需要为其他模块位置添加更多的--ignore dir
指令
当试图定位缓慢加载的模块(如请求
)时,这一点变得非常重要,这些模块在一台缓慢的机器上连续几分钟吐出数百万行源代码。正确使用--ignore dir
可以将时间缩短到几秒钟,并且只显示您自己代码中的行
$ time python -m trace --trace repost.py 2>&1 | wc
3710176 16165000 200743489
real 1m54.302s
user 2m14.360s
sys 0m1.344s
vs
这并不能真正回答你的问题;您要求提供与Python相当的set-x
。一种简单的近似方法是使用sys.settrace()
:
当运行时,它提供:
jcomeau@aspire:/tmp$ ./test.py
this first line should not trace
19: print 'this line and the following ought to show'
this line and the following ought to show
20: print "that's all folks"
that's all folks
21: TRACING.pop()
this last line should not trace
从跟踪输出中删除行“TRACING.pop()”留给读者作为练习
来源:和要使用
跟踪
模块获得与bash-x
适当等效的功能,需要使用--ignore dir
来阻止打印导入的每个模块的源代码行,例如python-m跟踪--trace--ignore dir/usr/lib/python2.7--ignore dir/usr/lib/pymodules repost.py
,根据其他模块位置的需要添加更多--忽略dir
指令
当试图定位缓慢加载的模块(如请求
)时,这一点变得非常重要,这些模块在一台缓慢的机器上连续几分钟吐出数百万行源代码。正确使用--ignore dir
可以将时间缩短到几秒钟,并且只显示您自己代码中的行
$ time python -m trace --trace repost.py 2>&1 | wc
3710176 16165000 200743489
real 1m54.302s
user 2m14.360s
sys 0m1.344s
vs
这并不能真正回答你的问题;您要求提供与Python相当的set-x
。一种简单的近似方法是使用sys.settrace()
:
当运行时,它提供:
jcomeau@aspire:/tmp$ ./test.py
this first line should not trace
19: print 'this line and the following ought to show'
this line and the following ought to show
20: print "that's all folks"
that's all folks
21: TRACING.pop()
this last line should not trace
从跟踪输出中删除行“TRACING.pop()”留给读者作为练习
资料来源:我非常喜欢@jcomeau_ictx,但它有一个小缺陷,这就是我对它进行扩展的原因。问题在于,只有当所有要跟踪的代码都在用python file.py
调用的文件(让我们称之为宿主文件)中时,jcomeau_ictx的“traceit”函数才能正常工作。如果调用任何导入的函数,就会得到很多没有代码的行号。原因是line=linecache.getline(sys.argv[0],lineno)
总是试图从主机文件中获取代码行(sys.argv[0]
)。这很容易纠正,因为实际包含跟踪代码行的文件名可以在frame.f_code.co_filename
中找到。这现在可能会产生大量的输出,这就是为什么人们可能希望有更多的控制
还有一点需要注意。根据sys.settrace()
文档:
每当发生错误时,将调用跟踪函数(将事件设置为“调用”)
输入新的本地范围
换句话说,要跟踪的代码必须在函数内部
为了保持一切整洁,我决定将一切都放在一个名为setx.py
的文件中。代码应该是非常自解释的。然而,Python3兼容性需要一段代码,它处理Python2和Python3在模块导入方式方面的差异。这是可以解释的。这段代码现在也可以与Python2和Python3一起使用
##setx.py
from __future__ import print_function
import sys, linecache
##adapted from https://stackoverflow.com/a/33449763/2454357
##emulates bash's set -x and set +x
##for turning tracing on and off
TRACING = False
##FILENAMES defines which files should be traced
##by default this will on only be the host file
FILENAMES = [sys.argv[0]]
##flag to ignore FILENAMES and alwas trace all files
##off by default
FOLLOWALL = False
def traceit(frame, event, arg):
if event == "line":
##from https://stackoverflow.com/a/40945851/2454357
while frame.f_code.co_filename.startswith('<frozen'):
frame = frame.f_back
filename = frame.f_code.co_filename
## print(filename, FILENAMES)
if TRACING and (
filename in FILENAMES or
filename+'c' in FILENAMES or
FOLLOWALL
):
lineno = frame.f_lineno
line = linecache.getline(filename, lineno)
print("{}, {}: {}".format(filename, lineno, line.rstrip()))
return traceit
sys.settrace(traceit)
及
然后,输出如下所示:
##file1.py
def func1():
return 7**2
setx_tester.py, 16: x=5
setx_tester.py, 17: print('the value of x is', x)
the value of x is 5
setx_tester.py, 20: print('-'*50)
--------------------------------------------------
setx_tester.py, 22: print(inner_func())
setx_tester.py, 12: return 15
15
setx_tester.py, 23: print(func1())
49
setx_tester.py, 24: print(func2())
abcabcabc
setx_tester.py, 26: print('-'*50)
--------------------------------------------------
setx_tester.py, 29: setx.FILENAMES.append(file1.__file__)
setx_tester.py, 30: print(inner_func())
setx_tester.py, 12: return 15
15
setx_tester.py, 31: print(func1())
**path to file**/file1.py, 2: return 7**2
49
setx_tester.py, 32: print(func2())
abcabcabc
setx_tester.py, 34: print('-'*50)
--------------------------------------------------
setx_tester.py, 36: setx.FILENAMES.pop()
setx_tester.py, 39: setx.FOLLOWALL = True
setx_tester.py, 40: print(inner_func())
setx_tester.py, 12: return 15
15
setx_tester.py, 41: print(func1())
**path to file**/file1.py, 2: return 7**2
49
setx_tester.py, 42: print(func2())
**path to file**/file2.py, 2: return 'abc'*3
abcabcabc
我非常喜欢@jcomeau_ictx,但它有一个小缺陷,这就是我对它进行扩展的原因。问题在于,只有当所有要跟踪的代码都在用python file.py
调用的文件(让我们称之为宿主文件)中时,jcomeau_ictx的“traceit”函数才能正常工作。如果调用任何导入的函数,就会得到很多没有代码的行号。原因是line=linecache.getline(sys.argv[0],lineno)
总是试图从主机文件中获取代码行(sys.argv[0]
)。这很容易纠正,因为实际包含跟踪代码行的文件名可以在frame.f_code.co_filename
中找到。这现在可能会产生大量的输出,这就是为什么人们可能希望有更多的控制
还有一点需要注意。根据sys.settrace()
文档:
每当发生错误时,将调用跟踪函数(将事件设置为“调用”)
输入新的本地范围
换句话说,要跟踪的代码必须在函数内部
为了保持一切整洁,我决定将一切都放在一个名为setx.py
的文件中。代码应该是非常自解释的。然而,Python3兼容性需要一段代码,它处理Python2和Python3在模块导入方式方面的差异。这是可以解释的。这段代码现在也可以与Python2和Python3一起使用
##setx.py
from __future__ import print_function
import sys, linecache
##adapted from https://stackoverflow.com/a/33449763/2454357
##emulates bash's set -x and set +x
##for turning tracing on and off
TRACING = False
##FILENAMES defines which files should be traced
##by default this will on only be the host file
FILENAMES = [sys.argv[0]]
##flag to ignore FILENAMES and alwas trace all files
##off by default
FOLLOWALL = False
def traceit(frame, event, arg):
if event == "line":
##from https://stackoverflow.com/a/40945851/2454357
while frame.f_code.co_filename.startswith('<frozen'):
frame = frame.f_back
filename = frame.f_code.co_filename
## print(filename, FILENAMES)
if TRACING and (
filename in FILENAMES or
filename+'c' in FILENAMES or
FOLLOWALL
):
lineno = frame.f_lineno
line = linecache.getline(filename, lineno)
print("{}, {}: {}".format(filename, lineno, line.rstrip()))
return traceit
sys.settrace(traceit)
及
然后,输出如下所示:
##file1.py
def func1():
return 7**2
setx_tester.py, 16: x=5
setx_tester.py, 17: print('the value of x is', x)
the value of x is 5
setx_tester.py, 20: print('-'*50)
--------------------------------------------------
setx_tester.py, 22: print(inner_func())
setx_tester.py, 12: return 15
15
setx_tester.py, 23: print(func1())
49
setx_tester.py, 24: print(func2())
abcabcabc
setx_tester.py, 26: print('-'*50)
--------------------------------------------------
setx_tester.py, 29: setx.FILENAMES.append(file1.__file__)
setx_tester.py, 30: print(inner_func())
setx_tester.py, 12: return 15
15
setx_tester.py, 31: print(func1())
**path to file**/file1.py, 2: return 7**2
49
setx_tester.py, 32: print(func2())
abcabcabc
setx_tester.py, 34: print('-'*50)
--------------------------------------------------
setx_tester.py, 36: setx.FILENAMES.pop()
setx_tester.py, 39: setx.FOLLOWALL = True
setx_tester.py, 40: print(inner_func())
setx_tester.py, 12: return 15
15
setx_tester.py, 41: print(func1())
**path to file**/file1.py, 2: return 7**2
49
setx_tester.py, 42: print(func2())
**path to file**/file2.py, 2: return 'abc'*3
abcabcabc
我搜索的是“相当于
bash-x
”。我搜索的是“相当于bash-x
”。我编写了一个默认情况下排除所有stdlib的小别名:alias pyx=“python-m trace--ignore dir$(python-c'import os,sys;print(os.pathsep.join)([p代表sys.path中的p,如果p中的“python3.5”)