【问题标题】:How to send email message only once in ThreadPool executed function?如何在 ThreadPool 执行功能中只发送一次电子邮件?
【发布时间】:2017-12-15 08:29:43
【问题描述】:

这是我用来使 API 操作速度提高 10 倍的函数:

def load_url(req, id, data, timeout):
    headers = {'Authorization': 'AT-API 111111222222333333344444445555555'}
    r = req.post("https://service.com/api/v1/compare", headers=headers, data=data, timeout=timeout)
    data = r.json()
    print id
    if data['error']:
        print data['error']
    else:
        c.execute("UPDATE offers SET valid = ? WHERE id = ?", ('valid' if data['data']['success'] else 'invalid', id))
        print data['data']['success']
        print data['data']['count']
    return r.json()


if __name__ == '__main__':
    ...
    with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
        future_to_url = {executor.submit(load_url, s, data['id'], data, 120): data for data in datas}
        for future in concurrent.futures.as_completed(future_to_url):
            url = future_to_url[future]
            try:
                data = future.result()

我们每 4 小时定期运行一次此脚本。在 load_url 中,我们打印并检查请求的状态,data['data']['count'] - 是一个月内剩余的调用量。我想在我们达到 5000 个或更少的电话后发送电子邮件通知,但只能发送一次。如何实现只发送一条消息,而不是5条消息而不是50条消息?我们使用 Sqlite3 来存储数据。

我们正在使用 Mailgun 发送电子邮件:

def send_simple_message(email_list):
    for email in email_list:
        response = requests.post(
            "https://api.mailgun.net/v3/newsletter.company.com",
            auth=("api", "key-1234567"),
            data={"from": "Mailgun Sandbox <postmaster@newsletter.mobupps.com>",
                "to": email,
                "subject": "Agent - we reached the limit by API",
                "html": "We reached the limit for agent" })

【问题讨论】:

    标签: python multithreading email threadpool threadpoolexecutor


    【解决方案1】:

    您可以使用锁定机制来防止多个线程执行send_simple_message 函数,并设置一个同步值来跟踪邮件是否已发送。

    import threading
    lock = threading.Lock()
    has_been_sent = False
    
    # then in your load_url function you could do something like
    if condition on count:
        with lock:
            if not has_beend_sent:
                # send mail
                has_been_sent = True
    

    【讨论】:

    • 我们每 4 小时定期运行一次此脚本,因此我们应确保记住它之前已发送过。
    • 它如何与 concurrent.futures.ThreadPoolExecutor 相适应?
    • 你说你使用的是sqlite,你可以在表格中记录你上次发送邮件的时间。
    • 你试过把我给你的那段代码放到 load_url 里吗?
    • 哪里会导致死锁?所有线程都有一个锁。
    猜你喜欢
    • 1970-01-01
    • 2012-12-12
    • 1970-01-01
    • 2014-11-30
    • 2011-01-23
    • 2016-05-06
    • 2020-03-26
    • 2017-10-27
    • 2014-05-23
    相关资源
    最近更新 更多