2013-08-14 3 views
10

Я хочу использовать отличный line_profiler, но только некоторое время. Чтобы сделать это, я добавляюПрофилирование python с использованием line_profiler - умный способ удалить операторы @profile на лету?

@profile 

перед каждым вызовом функции, например.

@profile 
def myFunc(args): 
    blah 
    return 

и выполнить

kernprof.py -l -v mycode.py args 

Но я не хочу, чтобы поставить @profile декораторов от руки каждый раз, потому что большую часть времени я хочу, чтобы выполнить код без них, и Я получаю исключение, если пытаюсь включить их, например

mycode.py args 

Есть ли золотая середина, где я могу динамически иметь декоратор снятые на основе некоторого условия переключения/аргумента, без необходимости делать вещи вручную и/или изменять каждую функцию слишком много?

+0

Я бы спросил, действительно ли мне нужно так часто профилироваться, что ему нужна такая поддержка. Я не говорю, что вы это делаете или не делаете, поэтому вам не нужно отвечать. Я просто нашел случай использования немного удивительным. – msw

+0

Код занимает много времени (часы на данный момент ...) для выполнения, поэтому на данный момент я хочу убить двух зайцев одним выстрелом для получения результатов и профилирования одновременно. Я полагаю, что профилирование я рассматриваю как непрерывный процесс (так как я новичок в этом/взволнован), поэтому я бы просто не использовал его в (многих) функциях, объявлял об этом и удалял все декораторы. – jtlz2

+0

Я бы не позволял чему-то часами без [* пробовать это *] (http://stackoverflow.com/a/4299378/23771). Это ничего не стоит и говорит вам, что именно происходит. –

ответ

13

Вместо удалить@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 декоратора.

+0

Огромное спасибо - и за быстрый ответ! Я пошел со вторым вариантом, и он работает блестяще. – jtlz2

+1

В Python3 вам нужно заменить '__builtin__' встроенными. Но это просто поиск и замена, все остальное все равно работает одинаково. –

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 
3

комментария, который вырос, чтобы стать вариантом @Martijin Питерс ответа.

Я предпочитаю не включать __builtin__. Без комментариев, было бы практически невозможно, чтобы кто-то еще догадался, что участвует line_profiler, без априори, зная это.

Глядя на kernprofline 199, достаточно создать экземпляр LineProfiler.

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

Импорт (явная) is better, чем глобально модификации builtins (неявное). Если профилирующие декораторы являются постоянными, то их происхождение должно быть ясным в самом коде.

При наличии line_profiler вышеуказанный подход обернет украшенные функции профайлерами при каждом запуске, независимо от того, работает ли он kernprof. Этот побочный эффект может быть нежелательным.

3

Вам не нужно импортировать __builtins__/builtins или LineProfiler вообще, вы можете просто полагаться на NameError при попытке для поиска profile:

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

Однако это должно быть включено в каждый файл, который использует profile, но он (постоянно) не изменяет глобальное состояние (встроенные) Python.