使用line_profiler进行Python分析 - 巧妙地在运行中删除@profile语句?

时间:2013-08-14 10:44:33

标签: python profiling decorator python-decorators

我想使用优秀的line_profiler,但只是在某些时候。为了使它工作,我添加

@profile
每次函数调用之前

,例如

@profile
def myFunc(args):
    blah
    return

并执行

kernprof.py -l -v mycode.py args

但是我不想每次都手动放置@profile装饰器,因为大多数时候我想要在没有它们的情况下执行代码,如果我试图包含它,我会得到一个例外他们,例如

mycode.py args

是否有一个快乐的媒介,我可以根据某些条件切换/参数动态删除装饰器,而不必手动操作和/或修改每个函数太多?

4 个答案:

答案 0 :(得分:17)

不是删除 @profile装饰线,而是提供您自己的传递无操作版本。

您可以将以下代码添加到项目的某个位置:

import __builtin__

try:
    __builtin__.profile
except AttributeError:
    # No line profiler, provide a pass-through version
    def profile(func): return func
    __builtin__.profile = profile

使用@profile装饰器在任何代码之前导入此代码,您可以使用带或不带有行分析器的代码。

因为虚拟装饰器是一个传递函数,所以执行性能不会受到影响(只有导入性能每个轻微的受影响)。

如果您不喜欢搞乱内置插件,可以将它作为一个单独的模块;说profile_support.py

import __builtin__

try:
    profile = __builtin__.profile
except AttributeError:
    # No line profiler, provide a pass-through version
    def profile(func): return func

(没有赋值__builtin__.profile)并在使用from profile_support import profile装饰器的任何模块中使用@profile

答案 1 :(得分:4)

您根本不需要导入__builtins__ / builtinsLineProfiler,在尝试查找NameError时,您只需依靠profile

try:
    profile
except NameError:
    profile = lambda x: x

但是,这需要包含在使用profile的每个文件中,但它不会(永久地)改变Python的全局状态(内置)。

答案 2 :(得分:3)

评论越来越成为@Martijin Pieters的变种。

我宁愿不涉及__builtin__。没有评论,其他人几乎不可能猜到line_profiler是否涉及,而且先验知道这一点。

查看kernprof line 199,即可实例化LineProfiler

try:
    from line_profiler import LineProfiler
    profile = LineProfiler()
except ImportError:
    def profile(func):
        return func

导入(显式)is better而非全局修改builtins(隐式)。如果剖析装饰器是永久性的,那么它们的原点应该在代码本身中清楚。

line_profiler出现时,无论是否由kernprof运行,上述方法都会在每次运行时使用分析器包装装饰函数。这种副作用可能是不希望的。

答案 3 :(得分:1)

我在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