2015-07-05 3 views
1

В моем сценарии .py у меня есть 2 функции. Один из них следует называть каждый 5 минут, а другой должен называться каждый 4 часа. Второй, однако, работает только один раз, когда сценарий запускается и никогда больше (в то время как функция 5 минут работает нормально).Вызов 2 функции python каждые N секунд

#!/usr/bin/env python 
import threading 

def five_min(): 
    threading.Timer(300, five_min).start() 
    print("5 min") 
def four_h(): 
    threading.Timer(14400, four_h).start() 
    print("4 h") 

five_min() 
four_h() 

Это весь код, я бегу это на Linux (Raspberry Pi)

P.S. Я думаю, что проблема может заключаться в том, что функция 4_h прерывается функцией 5_min.

+2

Вы можете определить функции, имена которых начинаются с числа? – khelwood

+0

Разве вы не должны ждать 4 часа после прямого вызова первой функции перед прямым вызовом второго? – martineau

+1

Возможный дубликат [Python threading.timer - функция повтора каждые 'n' секунд] (http://stackoverflow.com/questions/12435211/python-threading-timer-repeat-function-every-n-seconds) – wwii

ответ

0

Я также считаю, что проблема заключается в том, что 4_h() прерван другой функцией. Вы можете создать счетчик var внутри 5_min и вызвать 4_h() оттуда.

#!/usr/bin/env python 

import threading 

counter = 0 
def 5_min(): 
    threading.Timer(300, 5_min).start() 
    counter += 1 
    if (counter == 48): 
     counter = 0 
     4_h() 
    print("5 min") 
def 4_h(): 
    ... 

Возможно, это не лучшее решение, но это лучшее, что я знаю.

2

Ваша four_hour функция может быть повышение исключение до тогоthreading.Timer().start() вызывается снова:

import threading 
import logging 
logger = logging.getLogger(__name__) 

def five_min(): 
    t = threading.Timer(5, five_min).start() 
    logger.info("5 min") 
def four_hour(): 
    1/0 # <-- Raise an exception 
    threading.Timer(4, four_hour).start() 
    logger.info("4 h") 

logging.basicConfig(level=logging.DEBUG, 
        format='[%(asctime)s %(threadName)s] %(message)s', 
        datefmt='%M:%S') 

five_min() 
four_hour() 

дает

[57:54 MainThread] 5 min 
Traceback (most recent call last): 
    File "script.py", line 21, in <module> 
    four_hour() 
    File "script.py", line 12, in four_hour 
    1/0 
ZeroDivisionError: integer division or modulo by zero 
[57:59 Thread-1] 5 min 
[58:04 Thread-2] 5 min 
... 

(Примечание: Я изменил задержки так, что сценарий легче проверить. Как только вы находитесь , удовлетворенный качественным поведением сценария, вы можете задержать, как вы, желание.)


Примечания: as clemtoy points out как пор, пока нет необходимости в межпоточный или связи между процессами, это может быть проще use cron называть отдельных сценариев, которые работают в five_min и four_hour функции. Если вы делаете , вам нужна межпроцессная связь, но может быть лучше использовать cron, но вы должны были бы структурировать свой код по-разному, возможно, чтение из базы данных до узнать состояние прежних глобальных переменных.

+0

В исходном коде функции называются по-разному, 5_min, 4_h - это только имена.Извините за недоразумение – opengl

0

На мой взгляд, наилучшим способом планирования задач на Linux является использование cron. Если вы хотите, чтобы ваш скрипт добавлял задачу непосредственно в linux crontab, вы должны посмотреть на пакет python-crontab.

+0

Проблема с crontab заключается в том, что это «сбрасывает» все значения переменных, в то время как я храню данные в моем массиве, которые необходимо сохранить во время работы скрипта. – opengl

0

Кроме синтаксиса сейчас. Я предлагаю вам сделать это так:

from threading import Timer 
s = 0; m = 0 
fivesec_timer = None 
fourmin_timer = None 
def fivesec(): 
    global fivesec_timer, s 
    print s, "seconds passed after start" 
    s += 5 
    fivesec_timer = Timer(5, fivesec) 
    fivesec_timer.start() 

def fourmin(): 
    global fourmin_timer, m 
    print m, "minutes passed after start" 
    m += 4 
    fourmin_timer = Timer(4*60, fourmin) 
    fourmin_timer.start() 

fivesec() 
fourmin() 
# Here some code and blocking code 
# For instance: 
raw_input() 
fivesec_timer.cancel() 
fourmin_timer.cancel() 

This way, you can control your timers outside your functions. 

Don't do Timer(...).start(), especialy not inside a function (local scope). 
It should work fine, but you never know what and when garbage collector would clean up or something else occurs. You do not know how the _Timer() is implemented internally. 
And you don't have a hard reference to the timer (in a var) all the time. 
Mutual canceling out was probably caused by that, although this is clear speculation. 
threading module is well tested, yet you experienced problems. Keep your code neat. Best to be sure. 
Well, that is my view of the world. Someone will not agree. :D 
Смежные вопросы