2013-11-21 4 views
2

У меня есть много классов. Некоторые из них медленно инициализируются, и я хочу отложить некоторые из инициализации, используя cached properties. Первый шаг - определить, кто является виновником. Поэтому я хочу, чтобы время на следующий код:Идеи инициализации класса времени

class MyClass: 

    def __init__(self, ....): 
     # start measurement 
     ... 
     # end measurement, report 

Мои требования: результаты

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

Так что моя первая идея заключается в том, чтобы реализовать общую timeme функции:

def timeme(func):  
    def f(*args, **kwargs): 
     start = # get start timestamp 
     result = func(*args, **kwargs) 
     end = # get end timestamp 
     # report timespan 
     return result 
    return f 

(который может быть использован для времени какой-либо функции, а не только методы класса)

И теперь я могу сделать:

class MyClass: 

    @timeme 
    def __init__(self, ....): 
    ... 

Есть ли еще pythonic Способ сделать это? Некоторая стандартная поддержка библиотеки для этого? Поддержка инструментов? Какие-либо очевидные недостатки такого подхода?

+1

Отдельного слово приходит на ум: // профилирование //. – MrGumble

+0

Конечно, но я хочу сосредоточиться на конкретных областях. Мне не нужен полный и сложный отчет профайлера. И имея этот код, я могу включить его в производство, если захочу, имея его в журналах с реальной деятельностью - не путем воспроизведения прецедента с профилировщиком. – dangonfast

ответ

0

В стандартной библиотеке нет ничего подобного, кроме cProfile для регулярного профилирования.

Что бы я рекомендовал для вас, это создать простой метакласс, который будет обертывать методы __init__, если установлена ​​какая-либо глобальная переменная/окружение. Таким образом вам не понадобится загромождать ваш код с помощью декораторов отладки/профилирования.

Только отправная точка (не проверяла):

import functools 

# Python 3.3 for time.monotonic is required 
import time 

class TimedMeta(type): 
    timing_enabled = True 

    @classmethod 
    def _wrap_timeit(mcls, cls_name, meth): 
     @functools.wraps(meth) 
     def wrapped(*args, **kwargs): 
      start = time.monotonic() 
      try: 
       return meth(*args, **kwargs) 
      finally: 
       end = time.monotonic() 
       mcls._record_timing(cls_name, end - start) 

    @classmethod 
    def _record_timing(mcls, cls_name, timing): 
     raise NotImplementedError 

    def __new__(mcls, name, bases, dct): 
     if mcls.timing_enabled: 
      try: 
       init = dct['__init__'] 
      except KeyError: 
       pass 
      else: 
       dct['__init__'] = mcls._wrap_timeit(name, init) 

     return super().__new__(mcls, name, bases, dct) 

class Timed(metaclass=TimingMeta): 
    pass 

class Foo(Timed): 
    def __init__(self): 
     time.sleep(1.0) 
Смежные вопросы