我想使用出色的line_profiler,但只是部分时间。为了让它发挥作用,我添加了
@profile
在每次函数调用之前,例如
@profile
def myFunc(args):
blah
return
并执行
kernprof.py -l -v mycode.py args
但我不想每次都手动放入@profile
装饰器,因为大多数时候我都想在没有它们的情况下执行代码,如果我试图包含它们,我会遇到异常,例如
mycode.py args
有没有一种愉快的媒介,我可以根据一些条件切换/参数动态地删除装饰器,而不必手动操作和/或过多地修改每个函数?
与其删除@profile
装饰器行,不如提供您自己的直通无操作版本。
您可以将以下代码添加到您的项目中:
try:
# Python 2
import __builtin__ as builtins
except ImportError:
# Python 3
import builtins
try:
builtins.profile
except AttributeError:
# No line profiler, provide a pass-through version
def profile(func): return func
builtins.profile = profile
使用@profile
装饰器在任何代码之前导入它,您可以在激活或不激活行探查器的情况下使用代码。
因为伪decorator是一个传递函数,所以执行性能不会受到影响(只有导入性能受到轻微影响)。
如果你不喜欢破坏内置模块,你可以把它做成一个单独的模块;比如profile_support.py
:
try:
# Python 2
import __builtin__ as builtins
except ImportError:
# Python 3
import builtins
try:
profile = builtins.profile
except AttributeError:
# No line profiler, provide a pass-through version
def profile(func): return func
(没有对builtins.profile
的赋值),并在任何使用@profile
装饰器的模块中使用from profile_support import profile
。
您根本不需要导入__builtins__
/builtins
或LineProfiler
,您可以在尝试查找profile
:时简单地依赖NameError
try:
profile
except NameError:
profile = lambda x: x
然而,这需要包含在使用profile
的每个文件中,但它不会(永久)改变Python的全局状态(内置)。
一条评论,后来成为@Martijin Pieters答案的变体。
我宁愿根本不涉及__builtin__
。在没有评论的情况下,其他人几乎不可能猜测line_profiler
参与其中,也不可能事先知道这一点。
查看kernprof
行199,实例化LineProfiler
就足够了。
try:
from line_profiler import LineProfiler
profile = LineProfiler()
except ImportError:
def profile(func):
return func
导入(显式)比全局修改builtins
(隐式)要好。如果评测装饰器是永久性的,那么它们的来源应该在代码本身中是明确的。
在存在line_profiler
的情况下,无论是否由kernprof
运行,上述方法都将在每次运行时用profiler封装修饰函数。这种副作用可能是不希望的。
我使用的是Python 3.4 的以下修改版本
try:
import builtins
profile = builtins.__dict__['profile']
except KeyError:
# No line profiler, provide a pass-through version
def profile(func): return func
其他答案都是正确的,但在尝试"素数";类似CCD_ 21的脚本。这样初始化脚本可能很有用,例如,当您尝试使用numba
优化函数时,并且您不想在编译(或从文件系统缓存加载,即使使用numbas-cache=True param,这仍然会有很大的开销)时使行计时偏误。
问题是,安装运行会套住所有@profile
装饰器,并使它们在评测运行中变得毫无意义。
我通过将try转移到实际的decorator运行来解决这个问题,如下所示:
def profile2(f):
def s(*args, **kwargs):
try:
return profile(f)(*args, **kwargs)
except NameError:
return f(*args, **kwargs)
return s
并用CCD_ 24对我的所有功能进行了装饰。