Skip to content

Instantly share code, notes, and snippets.

@gennad
Created May 30, 2012 14:18
Show Gist options
  • Select an option

  • Save gennad/2836618 to your computer and use it in GitHub Desktop.

Select an option

Save gennad/2836618 to your computer and use it in GitHub Desktop.
Python task
import time
from wsgiref.util import setup_testing_defaults
from wsgiref.simple_server import make_server
def timeit(func):
def wrapper(*a, **k):
t1 = time.time()
it = iter(func(*a, **k))
try:
while True:
yield next(it)
except StopIteration:
pass # Or here
print time.time() - t1 # Only successful finish
return wrapper
@timeit
def app(environ, start_response):
start_response("200 OK", [])
for _ in xrange(1000):
yield "12345" * 10 * 1024 * 1024 # 52 428 800 bytes * 1000 about 50 GB
httpd = make_server('', 8080, app)
print "Serving on port 8080..."
httpd.serve_forever()
@gennad
Copy link
Author

gennad commented Jun 1, 2012

Хм ... Может я до конца не понял вопроса .... Вы спросили, как нам вычислить и вывести время если вставить it = iter(func...) в блок try и если нам надо время писать в случае успешного завершения . Если мы заменим finally на except StopIteration, тогда в случае неудачного завершения (вызова любого исключения кроме StopIteration внутри app) блок except wrapper'а не обработает, и распространит дальше по стеку вызовов. В случае удачного завершения (вызов исключения StopIteration), выполнения продолжится в блоке except и мы можем вывести время здесь или за блоком try.
Но тогда мы не сможем выполнить условие из 3 комментария (мы изменяем поведение функции тк любые вызовы StopIteration не относящиеся к нашему итератору, будут ловиться блоком except). Следовательно, мы не можем не изменить поведение функции, если вставим it = iter(func...) в блок try, следовательно оставляем его за блоком...
Если я что-то не понял, перефразируйте пожалуйста вопрос... Код обновил

@temoto
Copy link

temoto commented Jun 1, 2012

Не совсем так. Я сказал, что если it = iter(fun...) вставить внутрь try/finally, то поведение для списочных и генераторных WSGI приложений станет одинаковым: время будет всегда писаться, независимо от ошибок в приложении. Это может быть полезно. Но может оказаться так, что необходимо писать время только в случае успеха. Это просто часть требуемого поведения, независимо от положения и вообще наличия it = iter(fun...) в коде. Я ни в коем случае не прошу как-то поменять определённый код, чтобы он работал другим образом. Интересен только конечный результат, чтобы проходили все тесты.

Ловля исключений по задаче не требуется и в данном случае усложняет код. Не уверен, но возможно получится как-то выкрутиться с проверкой типа результата func(). Но это будет очень сложно и может сломаться на чём-нибудь вроде app -> return MyIterableClass(...). Есть решение, которое удовлетворяет всем требованиям, оно очень простое. Если хотите, покажу. Если что-то не так, извините, не хочу показаться агрессивным или злым, я не умею правильно общаться в таком формате.

@gennad
Copy link
Author

gennad commented Jun 1, 2012

Нет, мне наоборот интересно :)
Простое решение... Хм, может что-то вроде этого:

def wrapper(*a, **k):
  t1 = time.time()
  for i in func(*a, **k):
    yield i
  print time.time() - t1  # Only successful finish

return wrapper

Если это не то, скажите, какой правильный ответ )

@temoto
Copy link

temoto commented Jun 1, 2012

Да-да, это именно оно. Просто, надёжно и отвечает всем требованиям. Если есть требование писать время всегда, независимо от ошибок – весь for оборачивается в try/finally. Очень рад.

@gennad
Copy link
Author

gennad commented Jun 1, 2012

=) спасибо

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment