分析 Python 生成器

发布于 2024-09-16 14:49:23 字数 557 浏览 2 评论 0原文

我正在改编一个应用程序,该应用程序大量使用生成器来生成结果以提供 web.py Web 界面。

到目前为止,我可以将对 for 循环的调用和生成输出的语句包装在一个函数中,并使用 cProfile.run()runctx() 进行调用。从概念上讲:

def output():
    for value in generator():
        print(value)

cProfile.run('output()')

在 web.py 中,我必须按以下方式包装它,因为我想使用 yield 在每个迭代步骤中立即生成可能长时间运行的计算的输出:

class index:
    def GET(self):
        for value in generator():
            yield make_pretty_html(value)

有没有一种方法可以分析当它像第二个例子一样使用时,对生成器的所有调用都像第一个例子一样吗?

I'm adapting an application that makes heavy use of generators to produce its results to provide a web.py web interface.

So far, I could wrap the call to the for-loop and the output-producing statements in a function and call that using cProfile.run() or runctx(). Conceptually:

def output():
    for value in generator():
        print(value)

cProfile.run('output()')

In web.py, I have to wrap it the following way, since I want to immediately produce output from the potentially long-running computation in each iteration step using yield:

class index:
    def GET(self):
        for value in generator():
            yield make_pretty_html(value)

Is there a way to profile all calls to the generator like in the first example when it's used like in the second one?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

笨笨の傻瓜 2024-09-23 14:49:23

我终于找到了解决办法。通过此处返回分析的值。

import cProfile
import pstats
import glob
import math

def gen():
    for i in range(1, 10):
        yield math.factorial(i)

class index(object):
    def GET(self):
        p = cProfile.Profile()

        it = gen()
        while True:
            try:
                nxt = p.runcall(next, it)
            except StopIteration:
                break
            print nxt

        p.print_stats()

index().GET()

我还可以通过 文档并将它们组合起来存储/分析。

I finally found a solution. Return value of profiling via here.

import cProfile
import pstats
import glob
import math

def gen():
    for i in range(1, 10):
        yield math.factorial(i)

class index(object):
    def GET(self):
        p = cProfile.Profile()

        it = gen()
        while True:
            try:
                nxt = p.runcall(next, it)
            except StopIteration:
                break
            print nxt

        p.print_stats()

index().GET()

I also could merge multiple such profiling results (once I start giving unique file names) via documentation and store/analyze them combined.

平安喜乐 2024-09-23 14:49:23

听起来您正在尝试分析生成器上对“下一个”的每次调用?如果是这样,您可以将生成器包装在分析生成器中。像这样,注释掉的部分将把结果发送到日志或数据库。

def iter_profiler(itr):
  itr = iter(itr)
  while True:
    try:
      start = time.time()
      value = itr.next()
      end = time.time()
    except StopIteration:
      break
    # do something with (end - stop) times here
    yield value

然后,您可以使用 iter_profiler(generator()),而不是将生成器实例化为 generator()

It sounds like you're trying to profile each call to 'next' on the generator? If so, you could wrap your generator in a profiling generator. Something like this, where the commented off part will be sending the results to a log or database.

def iter_profiler(itr):
  itr = iter(itr)
  while True:
    try:
      start = time.time()
      value = itr.next()
      end = time.time()
    except StopIteration:
      break
    # do something with (end - stop) times here
    yield value

Then instead of instantiating your generator as generator() you would use iter_profiler(generator())

余生再见 2024-09-23 14:49:23

您可以只使用 time.time() 来分析您感兴趣的部分吗?只需获取当前时间并减去上次测量的时间即可。

Can you just use time.time() to profile the parts you are interested in? Just get the current time and subtract from the last time you made a measurement.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文