【问题标题】:Rate limiting generator wrapper?速率限制生成器包装器?
【发布时间】:2016-05-27 05:34:39
【问题描述】:

假设我有类似的东西

for user in users:
     send_email(user)

但由于我想减少拥堵,我想要类似的东西

for user in rate_limit(per_min=50, users):
     send_email(user)

一旦达到速率限制,rate_limit 函数就会简单地休眠并再次从 users 开始让步。

# something like this, where it just sleeps (until next min/sec cycle) 
# once the number of iterations per_min or per_sec have been achieved.

def rate_limit(per_min=None, per_sec=None, objects):
    ???

问题是我不知道如何以这种形式保存状态(在经过的时间/发送的电子邮件的意义上)。

有人有什么想法吗?

【问题讨论】:

  • 为避免不必要的延误,您可以use RatedSemaphore(50, 60)
  • @J.F.Sebastian 我从未见过在多处理/多线程情况之外使用信号量。它会在我的情况下工作吗?原谅我的无知
  • 是的。我链接的答案中的第一个代码示例没有创建自己的新线程(尽管信号量创建了一个后台线程来生成令牌)。在您的情况下,它可能看起来像:for user in users: with rate_limit: send_email(user)。如果rate_limit = RatedSemaphore(50, 60) 则保证循环不会每分钟发送超过 50 封电子邮件。

标签: python python-3.x


【解决方案1】:

您可能正在寻找time.sleep()

  1. 生成一个对象
  2. 睡觉
  3. 从第 1 步开始重复

例如:

import time

def rate_limit(objects, per_min=None):
    sleep_time = 60 / per_min if per_min else 0
    for obj in objects:
        yield obj
        time.sleep(sleep_time)

问题是我不知道如何以这种形式保存状态(在经过的时间/发送的电子邮件的意义上)。

这将自动保存状态,因为yield 只是暂停函数并在再次调用函数后继续。如果你想知道花费的时间和发送邮件的数量,你可以简单地添加一个计数器:

def rate_limit(objects, per_min=None):
    sleep_time = 60 / per_min if per_min else 0
    for count, obj in enumerate(objects):
        yield obj
        print('Sent email {0} at {1} seconds.'.format(count, count * sleep_time))
        time.sleep(sleep_time)

【讨论】:

  • 感谢您的帮助。我会按照你的例子来做
【解决方案2】:

只需使用time.sleep,这将暂停当前线程给定的秒数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-02-10
    • 1970-01-01
    • 2021-05-16
    • 2022-10-14
    • 2020-03-25
    • 2018-11-11
    • 2017-08-20
    • 2022-10-13
    相关资源
    最近更新 更多