Python запускает две функции с разными таймерами в одном демоне

Я использую демон шаблона python, обсуждаемый здесь в двух разные сценарии для запуска двух отдельных демонов. Я хотел бы объединить их в один сценарий демона с одним файлом блокировки и т. д. Однако у каждого есть свой таймер цикла: один на 1 минуту, а другой на 5 минут. Я начинаю с этого:

import os
import subprocess
import time
from daemon import runner

class App():
    def __init__(self):
        self.stdin_path = '/dev/null'
        self.stdout_path = '/dev/tty'
        self.stderr_path = '/dev/tty'
        self.pidfile_path =  '/tmp/test.pid'
        self.pidfile_timeout = 5
    def run(self):

        try:
            while True:

                print "hello!"

                # set the sleep time for repeated action here:
                time.sleep(1)

        except Exception, e:
            raise


app = App()
daemon_runner = runner.DaemonRunner(app)
daemon_runner.do_action()

Очевидно, что нужно было бы создать еще один класс, но я хочу, чтобы базовые вещи, такие как pidfile, оставались постоянными.


person secumind    schedule 21.05.2012    source источник
comment
Сохраните константы в классе App и создайте подкласс для каждого приложения.   -  person John La Rooy    schedule 22.05.2012


Ответы (2)


Я не совсем понимаю, почему вы хотите это сделать, но это должно сработать:

Сделайте функции run_A и run_B для выполнения двух независимых действий (очевидно, не с этими именами), включая сон и так далее. На самом деле это не имеет значения, но может иметь смысл иметь их вне класса App.

Затем создайте функцию run, которая выглядит так:

def run(self):
    threads = [
         threading.Thread(target=run_A),
         threading.Thread(target=run_B)
    ]

    for thread in threads:
         thread.start()
    for thread in threads:
         thread.join()

Это создаст отдельный поток для каждого задания, который затем может продолжить свою работу. Если у вас есть общие ресурсы между заданиями, вам придется беспокоиться о блокировке.

Это предполагает, что задания выполняются быстро и точное время не имеет большого значения; из-за GIL CPython только один поток будет одновременно выполнять операторы Python, поэтому, если они всплывают в в то же время они будут работать немного медленнее. Вы можете тривиально переключить это на использование multiprocessing, если хотите, чтобы они могли работать параллельно.

Это приведет к некоторому «смещению таймера», потому что вы используете sleep (как и ваши демоны, если они работают независимо). Если это важно, вы можете вместо этого использовать прерывания или рассчитать время до следующего кратного пяти минут, а не просто спать пять минут.

person Danica    schedule 22.05.2012

Если нет необходимости в том, чтобы ваша более длинная задержка выполнялась точно по времени, вы можете использовать простой аккумулятор, чтобы отслеживать, сколько времени было использовано несколькими циклами более короткого действия. Приведенный ниже код будет работать идеально, если LONG_DELAY является точным целым числом, кратным SHORT_DELAY. Если это число не является точным кратным, более длинный цикл все равно будет выполняться в среднем с запрошенным периодом, но задержка может быть короче или длиннее на величину до SHORT_DELAY для любого заданного прохода:

SHORT_DELAY = 60 # 1 minute
LONG_DELAY = 300 # 5 minutes

accum = LONG_DELAY

while True:
    do_short_delay_action()

    if accum >= LONG_DELAY:
        do_long_delay_action()
        accum -= LONG_DELAY

    time.sleep(SHORT_DELAY)
    accum += SHORT_DELAY
person Blckknght    schedule 22.05.2012