2013-06-25 2 views
2

Im пытается запустить отправить электронное письмо с задержкой, так как условное отправление электронной почты может быть включено в течение некоторого времени, и я не хочу получать и бесконечное количество уведомлений по электронной почте ...Python, threading.timer объект не будет запускать таймер функции?

Для этого я ' m пытается запустить threading.timer, чтобы дать ему задержку и отправлять по электронной почте только каждые 15 минут ... Я пробовал длительную 900-секундную задержку на объекте .timer, и он работает (используется сценарий времени) ... но когда я запускаю его чтобы отправить сообщение электронной почты он сначала отправляет сообщение электронной почты, а затем вводит таймер не работает другие части сценария ... функция электронной почты работает просто отлично ... работает 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 количество .time множества ... т.е.

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 секунд я получаю 36 писем через 300 секунд .. ?? Любая идея почему? (Reformat из комментария ниже)

После прочтения ответа на вопросник я понял проблему ... Я все еще знал, что на 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" 

ответ

2

В качестве второго аргумента для 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.


Что касается вопроса с 36 писем в 300 секунд, в вашем коде:

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 письма, вы должны 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 различных Timer s созданы, они таймаут почти в то же самое время, так что вы будете видеть все email sent! появляются в том же время. Вы можете изменить тайм-аут, чтобы принять во внимание:

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

В приведенном выше коде, вы увидите email sent! появляются один за один раз с интервалом около 1 секунды.

Наконец, я бы добавил, что у вас нет возможности контролировать, когда будет получено электронное письмо. Этими различными способами обрабатываются разные службы, поэтому нет возможности гарантировать, что при запуске вашего кода получатель получит электронное письмо каждые 100 секунд.

+0

работает как шарм. Я все еще новичок в python и не видел функцию лямбда. Я сделаю некоторое чтение. – user2520982

+0

После игры с ним ... он выполняет сон, но отправляет все письма. .. не один адрес электронной почты каждый X количество .time множества ... т.е. ' п = 300 начало = time.time() в то время как (time.time() - начало <п): led_temp = 56 , если led_temp> 55: (: 'температура Свет Перегрев' send_email (, led_temp) 100, лямбда) t.start() ' Если т = threading.Timer Я запускаю этот код Im, имитируя временное предупреждение, превышающее значение в течение 300 секунд. Вместо того, чтобы получать по электронной почте каждые 100 секунд, я получаю 36 писем через 300 секунд .. ?? Любая идея почему? – user2520982

+0

@ user2520982 Можете ли вы отредактировать свой вопрос и рассказать о проблемах сейчас? Код в комментариях вообще не читается. Электронные письма AFAIK не гарантируются мгновенно, поэтому поставщики и т. Д. Могут одновременно отправлять более одного электронного письма. – Bakuriu

0

Не уверен, если это то, что вы ищете, но если ваша проблема в том, что нить таймера выполняется независимо от основного сценария, вы можете join, что нить нравится так:

t.start() 
t.join() # will wait until the thread `t` has finished 

Но этот вид побеждает цель запуска вашей функции в отдельном потоке. Таким образом, вы можете захотеть просто time.sleep в течение некоторого времени до или после отправки этого сообщения электронной почты.

Кстати, убедитесь, что вызов send_email('Tank temperature Overheat',tank_temp) фактически возвращает функцию, которая будет вызываться, когда поток таймера запущен и не отправляет фактическую почту.