Python,threading.timer对象不会运行定时器函数?

标签 python function timer delay sleep

我正在尝试延迟发送电子邮件,因为发送电子邮件的条件可能会持续很长一段时间,并且我不想接收无限量的电子邮件警报...

为此,我尝试使用 threading.timer 给它一个延迟,并且每 15 分钟才发送一次电子邮件...我在 .timer 对象上尝试了 900 秒的长延迟,它起作用了(使用时间脚本)。 ..但是当我运行它来发送电子邮件时,它首先发送电子邮件,然后进入计时器而不运行脚本的其他部分...电子邮件功能工作得很好...运行 python 2.6.6

#!/usr/bin/env python

import time
import smtplib #for sending emails when warning
import threading

if True: #the possibility exists that the conditional is met several times thus sending lots of emails
    t = threading.Timer(300,send_email('Tank temperature Overheat',tank_temp))
    t.start() # after 300 seconds, the email will be sent but the script will keep running
print "rest of the script keeps running"
print "keeps running the scrpit and after 300s the email is sent"

关于为什么它不起作用或其他解决方法有什么想法吗?

玩完后...它会休眠,但会发送所有电子邮件...而不是每隔 X 时间设置发送一封电子邮件...即

n=300

start = time.time()

while (time.time() - start < n):

    led_temp = 56

        if led_temp > 55:
        t = threading.Timer(100, lambda: send_email('Lights temperature Overheat',led_temp))
        t.start()

我不是每 100 秒收到一封电子邮件,而是在 300 秒后收到 36 封电子邮件..??知道为什么吗? (根据下面的评论重新格式化)

在阅读了有关线程的答案后,我理解了问题...我仍然了解 python,并且从未使用过用户线程,所以我想这就是我在创建无数线程时收到的 36 封电子邮件的根本原因...我通过使用标志修复了它,并测试了如下代码:

def raise_flag():
    global start
    interval = 300
    if start > interval:
        start = 0
        flag = True
        print "Flag True, sending email"
        return flag
    else:
        flag = False
        start = start + 1
        print "Flag OFF", start
        time.sleep(1)
        return flag

led_temp = 27
while led_temp > 26:
    flag = raise_flag()
    if flag:
        send_email('Tank temperature Overheat',led_temp)
        flag = False
        print "Sent email"

最佳答案

作为 timer 的第二个参数,您应该传递一个可调用的,但在您的情况下,您正在调用该函数并将结果传递给 threading.Timer。您应该改用 lambda 表达式:

#!/usr/bin/env python

import time
import smtplib
import threading

if True:
    t = threading.Timer(300, lambda: send_email('Tank temperature Overheat',tank_temp))
    t.start() 
print "rest of the script keeps running"
print "keeps running the scrpit and after 300s the email is sent"

表达式:

lambda: send_email('Tank temperature Overheat',tank_temp)

评估一个不带参数的函数,当调用时使用该参数执行send_email,而在您的代码中您有:

t = threading.Timer(300,send_email('Tank temperature Overheat',tank_temp))

这将首先评估所有参数,然后调用 send_email,然后然后创建 Timer 对象。


关于 300 秒内 36 封电子邮件的问题,在您的代码中:

n=300

start = time.time()

while (time.time() - start < n):

    led_temp = 56

        if led_temp > 55:
        t = threading.Timer(100, lambda: send_email('Lights temperature Overheat',led_temp))
        t.start()

while 将在 300 秒的迭代期间创建大量线程。我不知道为什么你认为这个循环应该每 100 秒向你发送一封电子邮件。每个线程都会在 100 秒后向您发送一封电子邮件,但线程数量很多。

如果您只想发送 3 封电子邮件,那么您应该在 3 次迭代后break 跳出循环。此外,迭代可能太快,因此所有计时器几乎会立即发送所有电子邮件,因为它们的超时时间几乎相等。

您可以通过以下代码看到这个问题:

>>> import threading
>>> import threading
>>> def send_email(): print("email sent!")
... 
>>> for _ in range(5):
...     t = threading.Timer(7, send_email)
...     t.start()
... 
>>> email sent!
email sent!
email sent!
email sent!
email sent!

尽管创建了 5 个不同的计时器,但它们几乎同时超时,因此您会看到所有已发送的电子邮件! 同时出现。您可以修改超时以考虑到这一点:

>>> for i in range(5):
...     t = threading.Timer(7 + i, send_email)
...     t.start()
... 
>>> email sent!
email sent!
email sent!
email sent!
email sent!

在上面的代码中,您将看到一次出现一封电子邮件已发送!,间隔大约为 1 秒。

最后我要补充一点,您无法控制何时收到电子邮件。不同的服务会以不同的方式处理此问题,因此无法保证在运行代码时收件人每 100 秒都会收到一封电子邮件。

关于Python,threading.timer对象不会运行定时器函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17303187/

相关文章:

c - STM32定时器自动重载预载

c# - 如何实现每小时运行一次但也可以从 .aspx 页面触发的作业?

python - 如何在 tensorflow 中制作 reshape 层?

python - Django迁移应用名称更改(事件项目)

c++ - 在 Win32 C++ 中调用未导出的函数

Javascript 定时安全保护垃圾邮件

Python 列表 append 问题

python - 如何将 Numpy 中的累积和应用于条件为前一个值的切片?

Python return 忽略多个参数

javascript - 如何使用 AngularJS 将对象插入数组