Есть ли высокоуровневый модуль профилирования для Python? - PullRequest
4 голосов
/ 23 сентября 2010

Я хочу профилировать мой код Python.Я хорошо осведомлен о cProfile и использую его, но он слишком низкоуровневый.(Например, нет даже простого способа получить возвращаемое значение из функции, которую вы профилируете.)

Одна из вещей, которую я хотел бы сделать: я хочу взять функцию в моемзапрограммируйте и настройте его на профилирование на лету во время работы программы.

Например, допустим, у меня есть функция heavy_func в моей программе.Я хочу запустить программу и иметь функцию heavy_func, а не сам профиль.Но иногда во время выполнения моей программы я хочу изменить heavy_func на профилирование во время работы.(Если вам интересно, как я могу манипулировать вещами во время работы программы: я могу сделать это либо с помощью отладочного зонда, либо из оболочки, встроенной в мое приложение с графическим интерфейсом.)

Модуль уже написанчто делает такие вещи?Я могу написать это сам, но я просто хотел спросить раньше, чтобы не изобретать велосипед.

Ответы [ 2 ]

1 голос
/ 23 сентября 2010

Это может быть немного изнурительным, но эта техника должна помочь вам найти "узкие места", это то, что вы хотите сделать. Вы совершенно уверены, на какой рутине вы хотите сосредоточиться. Если вы должны сосредоточиться на этой рутине, это докажет, что вы правы. Если настоящая проблема (проблемы) где-то еще, она покажет вам, где они находятся.

Если вам нужен утомительный список причин, по которым посмотрите здесь .

0 голосов
/ 24 декабря 2010

Я написал свой собственный модуль для него.Я назвал это cute_profile. Вот код . Вот тесты .

Вот сообщение в блоге, объясняющее, как его использовать.

Это часть GarlicSim поэтому, если вы хотите использовать его, вы можете установить garlicsim и сделать from garlicsim.general_misc import cute_profile.

Если вы хотите использовать его в коде Python 3, просто установите Python3 вилки из garlicsim.

Вот устаревшая выдержка из кода:

import functools

from garlicsim.general_misc import decorator_tools

from . import base_profile


def profile_ready(condition=None, off_after=True, sort=2):
    '''
    Decorator for setting a function to be ready for profiling.

    For example:

        @profile_ready()
        def f(x, y):
            do_something_long_and_complicated()

    The advantages of this over regular `cProfile` are:

     1. It doesn't interfere with the function's return value.

     2. You can set the function to be profiled *when* you want, on the fly.

    How can you set the function to be profiled? There are a few ways:

    You can set `f.profiling_on=True` for the function to be profiled on the
    next call. It will only be profiled once, unless you set
    `f.off_after=False`, and then it will be profiled every time until you set
    `f.profiling_on=False`.

    You can also set `f.condition`. You set it to a condition function taking
    as arguments the decorated function and any arguments (positional and
    keyword) that were given to the decorated function. If the condition
    function returns `True`, profiling will be on for this function call,
    `f.condition` will be reset to `None` afterwards, and profiling will be
    turned off afterwards as well. (Unless, again, `f.off_after` is set to
    `False`.)

    `sort` is an `int` specifying which column the results will be sorted by.
    '''


    def decorator(function):

        def inner(function_, *args, **kwargs):

            if decorated_function.condition is not None:

                if decorated_function.condition is True or \
                   decorated_function.condition(
                       decorated_function.original_function,
                       *args,
                       **kwargs
                       ):

                    decorated_function.profiling_on = True

            if decorated_function.profiling_on:

                if decorated_function.off_after:
                    decorated_function.profiling_on = False
                    decorated_function.condition = None

                # This line puts it in locals, weird:
                decorated_function.original_function

                base_profile.runctx(
                    'result = '
                    'decorated_function.original_function(*args, **kwargs)',
                    globals(), locals(), sort=decorated_function.sort
                )                
                return locals()['result']

            else: # decorated_function.profiling_on is False

                return decorated_function.original_function(*args, **kwargs)

        decorated_function = decorator_tools.decorator(inner, function)

        decorated_function.original_function = function
        decorated_function.profiling_on = None
        decorated_function.condition = condition
        decorated_function.off_after = off_after
        decorated_function.sort = sort

        return decorated_function

    return decorator
...