2016-01-24 7 views
3

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

@log_time("log.txt", 35) 
def some_function(...): 
    ... 
    return result 

и

from functools import wraps 

def log_time(path_to_logfile, interval): 
    ... 

log.txt так что будет выглядеть как

Time elapsed: 0h 0m 35s 
Time elapsed: 0h 1m 10s 
Time elapsed: 0h 1m 45s 

Есть идеи?

+2

Это спецификация, а не вопрос. – chepner

ответ

2

Хорошо, я понял что-то в конце с нитками. Спасибо за все предложения!

import codecs, threading, time 
from functools import wraps 

def log_time(logpath="log.txt", interval=5): 

    def log_time_decorator(func): 
     @wraps(func) 
     def wrapper(*args, **kwargs): 
      t = threading.Thread(target=func, args=args, kwargs=kwargs) 
      log_entries = 0 
      with codecs.open(logpath, "wb", "utf-8") as logfile: 
       start_time = time.time() 
       t.start() 
       while t.is_alive(): 
        elapsed_time = (time.time() - start_time) 
        if elapsed_time > interval * log_entries: 
         m, s = divmod(elapsed_time, 60) 
         h, m = divmod(m, 60) 
         logfile.write("Elapsed time: %2dh %2dm %2ds\n" %(h, m, s)) 
         log_entries += 1 
     return wrapper 
    return log_time_decorator 

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

EDIT1: Удален ненужный переменную и добавил хороший формат для logwriting (см this)

EDIT2: Даже если другие пользователи отклонили его редактировать, я хочу, чтобы включить версию из Piotr Dabkowski, потому что он работает с возвращаемая стоимость:

def log_time(logpath="log.txt", interval=5): 

    def log_time_decorator(func): 
     @wraps(func) 
     def wrapper(*args, **kwargs): 
      RESULT = [None] 
      def temp(): 
       RESULT[0] = func(*args, **kwargs) 
      t = threading.Thread(target=temp) 
      log_entries = 0 
      with codecs.open(logpath, "wb", "utf-8") as logfile: 
       start_time = time.time() 
       t.start() 
       while t.is_alive(): 
        elapsed_time = (time.time() - start_time) 
        if elapsed_time > interval * log_entries: 
         m, s = divmod(elapsed_time, 60) 
         h, m = divmod(m, 60) 
         logfile.write("Elapsed time: %2dh %2dm %2ds\n" %(h, m, s)) 
         log_entries += 1 
      return RESULT[0] 
     return wrapper 
    return log_time_decorator 
+0

кажется довольно прохладным +1 для этого –

0

Быстро складывается, но работает в тесте с помощью @timeit на нескольких функциях.

import logging 
logging.basicConfig(
    level=logging.DEBUG, 
    filename='myProgramLog.txt', 
    format=' %(asctime)s - %(levelname)s - %(message)s') 

import time             

def timeit(method): 

    def timed(*args, **kw): 
     ts = time.time() 
     result = method(*args, **kw) 
     te = time.time() 

     logging.debug('%r (%r, %r) %2.2f sec' % \ 
       (method.__name__, args, kw, te-ts)) 
     return result 

    return timed 

Источники: https://www.andreas-jung.com/contents/a-python-decorator-for-measuring-the-execution-time-of-methods, https://automatetheboringstuff.com/chapter10/

EDIT: Я считаю, Python поставляется с довольно хорошим модулем регистрации; зачем изобретать колесо?

4

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

def log_time(path_to_logfile, interval): 
    def log(func): 
     # 'wrap' this puppy up if needed 
     def wrapped(*args, **kwargs): 
      # start timing 
      func(*args, **kwargs) 
      # stop timing 
      with open(path_to_logfile, 'a') as f: 
       pass # functionality 
     return wrapped 
    return log 

Теперь вы можете украсить функции, и выход будет написано в path_to_logfile. Так, например, украшения foo здесь:

@log_time('foo.txt', 40) 
def foo(i, j): 
    print(i, j) 

foo(1, 2) 

Примет Foo и выполнить его. Вам необходимо указать time и написать содержимое в файл. Вы должны поэкспериментировать с декораторами еще больше и прочитать их, хорошую статью на Decorators exist at the Python Wiki.

+0

Но это будет регистрироваться только после завершения функции, не так ли? Однако я ищу что-то, что регистрируется во время выполнения функции. Извините, если мой вопрос не был правильно сформулирован. – Kaleidophon

+0

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

Смежные вопросы