-
-
Save gennad/2836618 to your computer and use it in GitHub Desktop.
| 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() |
Не совсем так. Я сказал, что если it = iter(fun...) вставить внутрь try/finally, то поведение для списочных и генераторных WSGI приложений станет одинаковым: время будет всегда писаться, независимо от ошибок в приложении. Это может быть полезно. Но может оказаться так, что необходимо писать время только в случае успеха. Это просто часть требуемого поведения, независимо от положения и вообще наличия it = iter(fun...) в коде. Я ни в коем случае не прошу как-то поменять определённый код, чтобы он работал другим образом. Интересен только конечный результат, чтобы проходили все тесты.
Ловля исключений по задаче не требуется и в данном случае усложняет код. Не уверен, но возможно получится как-то выкрутиться с проверкой типа результата func(). Но это будет очень сложно и может сломаться на чём-нибудь вроде app -> return MyIterableClass(...). Есть решение, которое удовлетворяет всем требованиям, оно очень простое. Если хотите, покажу. Если что-то не так, извините, не хочу показаться агрессивным или злым, я не умею правильно общаться в таком формате.
Нет, мне наоборот интересно :)
Простое решение... Хм, может что-то вроде этого:
def wrapper(*a, **k):
t1 = time.time()
for i in func(*a, **k):
yield i
print time.time() - t1 # Only successful finish
return wrapper
Если это не то, скажите, какой правильный ответ )
Да-да, это именно оно. Просто, надёжно и отвечает всем требованиям. Если есть требование писать время всегда, независимо от ошибок – весь for оборачивается в try/finally. Очень рад.
=) спасибо
Хм ... Может я до конца не понял вопроса .... Вы спросили, как нам вычислить и вывести время если вставить it = iter(func...) в блок try и если нам надо время писать в случае успешного завершения . Если мы заменим finally на except StopIteration, тогда в случае неудачного завершения (вызова любого исключения кроме StopIteration внутри app) блок except wrapper'а не обработает, и распространит дальше по стеку вызовов. В случае удачного завершения (вызов исключения StopIteration), выполнения продолжится в блоке except и мы можем вывести время здесь или за блоком try.
Но тогда мы не сможем выполнить условие из 3 комментария (мы изменяем поведение функции тк любые вызовы StopIteration не относящиеся к нашему итератору, будут ловиться блоком except). Следовательно, мы не можем не изменить поведение функции, если вставим it = iter(func...) в блок try, следовательно оставляем его за блоком...
Если я что-то не понял, перефразируйте пожалуйста вопрос... Код обновил