Python profiling using line_profiler – clever way to remove @profile statements on-the-fly

decoratorprofilingpythonpython-decorators

I want to use the excellent line_profiler, but only some of the time. To make it work I add

@profile

before every function call, e.g.

@profile
def myFunc(args):
    blah
    return

and execute

kernprof.py -l -v mycode.py args

But I don't want to have to put the @profile decorators in by hand each time, because most of the time I want to execute the code without them, and I get an exception if I try to include them, e.g.

mycode.py args

Is there a happy medium where I can dynamically have the decorators removed based on some condition switch/argument, without having to do things manually and/or modify each function too much?

Best Answer

Instead of removing the @profile decorator lines, provide your own pass-through no-op version.

You can add the following code to your project somewhere:

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

Import this before any code using the @profile decorator and you can use the code with or without the line profiler being active.

Because the dummy decorator is a pass-through function, execution performance is not impacted (only import performance is every so lightly affected).

If you don't like messing with built-ins, you can make this a separate module; say 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

(no assignment to builtins.profile) and use from profile_support import profile in any module that uses the @profile decorator.