14

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

@profile

在每个函数调用之前,例如

@profile
def myFunc(args):
    blah
    return

并执行

kernprof.py -l -v mycode.py args

但是我不想@profile每次都手动放入装饰器,因为大多数时候我想在没有它们的情况下执行代码,如果我尝试包含它们,我会遇到异常,例如

mycode.py args

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

4

5 回答 5

23

提供您自己的传递无操作版本,而不是删除装饰器行@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,您可以在有或没有激活线分析器的情况下使用代码。

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

如果你不喜欢弄乱内置插件,你可以把它做成一个单独的模块;说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)并在使用装饰器from profile_support import profile的任何模块中使用。@profile

于 2013-08-14T10:47:18.777 回答
9

您不需要导入__builtins__/builtins或根本不需要,您可以在尝试查找时LineProfiler简单地依赖 a :NameErrorprofile

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

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

于 2017-05-13T17:58:27.340 回答
6

逐渐成为@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. 这种副作用可能是不希望的。

于 2015-08-29T01:19:11.977 回答
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
于 2015-05-27T18:40:49.373 回答
0

其他答案是正确的,但是在尝试使用类似kernprof -l --setup script.py script.py. 像这样启动脚本可能很有用,例如,当您尝试优化您的函数numba并且您不想通过编译(或从文件系统缓存加载,即使使用 numbas cache=True参数)。

问题是安装程序运行noops 你所有的@profile装饰器并使它们对分析运行没有意义。

我通过将 try except 移动到实际的装饰器来解决这个问题,如下所示:

def profile2(f):
    def s(*args, **kwargs):
        try:
            return profile(f)(*args, **kwargs)
        except NameError:
            return f(*args, **kwargs)
    return s

并用@profile2.

于 2021-10-04T08:17:52.640 回答