Python запускает процесс в определенное время и завершает его в определенное время - PullRequest
0 голосов
/ 22 февраля 2019

Это пример кода Python для запуска процесса каждые 5 секунд до 1 часа ночи.

def run_check():
  mythrd =threading.Timer(5.0, run_check)
  mythrd.start()
  time = datetime.now()
  domystuff()

  if time.hour == 1:
    mythrd.cancel()

run_check()

Я хотел запустить поток в определенное время.Поэтому я изменил этот код, как показано ниже:

mythrd = None

def run_check():
  while (True):

    now = datetime.now
    if now().hour == 16 and now().minute == 30 and now().second == 30:
      mythrd.start()
      time.sleep(1)
    if mythrd.is_alive():
      domystuff()

    if datetime.now().hour == 16 and datetime.now().minute == 31:
        mythrd.cancel()

mythrd =threading.Timer(5.0, run_check)
run_check()

Ранее я держал объект mythrd внутри функции run_check.Если я инициализирую внутри функции run_check, она будет действовать как новый объект.И это снова сработает.Поэтому я определил функцию mythrd как глобальный объект.Но он продолжает работать.Я хочу начать процесс в определенное время и закончить его в определенное время.Что не так в моем коде?

Ответы [ 2 ]

0 голосов
/ 22 февраля 2019

Я реализовал это решение для вас:

from datetime import datetime as dt
import threading
import time

class test(object):

    def __init__(self):
        self.run_permission = False

        self.start_time = [16,30,30] # Hours, Minutes, Seconds
        self.end_time = [18,41,00] # Hours, Minutes, Seconds

        self.timer_sched_time = 5 # seconds

        threading.Thread(name="time_checker", target=self.check_time, args=(self.start_time, self.end_time,)).start()
        threading.Thread(name="scheduled_job", target=self.Timer, args=(self.timer_sched_time, )).start()

        while True:
            time.sleep(10)

    def timer_job(self, unix_time, human_time):
        print "Unix time: %s  Human time: %s \n" % (unix_time, human_time)

    def Timer(self, delay):
        while True:
            try:
                time_remaining = delay-time.time()%delay
                time.sleep(time_remaining)

                unix_time = str(int(round(time.time()*1000)))
                human_time = str(dt.now())

                if(self.run_permission):
                    self.timer_job(unix_time, human_time)

            except Exception, ex:
                raise ex

    def check_time(self, start_execution_time, end_execution_time):
        while True:
            now = dt.now()

            if(now.hour >= start_execution_time[0] and now.minute >= start_execution_time[1] and now.second >= start_execution_time[2]):
                self.run_permission = True

            if(now.hour >= end_execution_time[0] and now.minute >= end_execution_time[1] and now.second >= end_execution_time[2]):
                self.run_permission = False

test()

Первым делом импортируйте нужную вам библиотеку:

from datetime import datetime as dt
import threading
import time

Создайтекласс с именем test:

class test(object):

Определите __init__, он будет выполнен при создании теста класса при вызове его с использованием test():

def __init__(self):
        self.run_permission = False

        self.start_time = [16,30,30] # Hours, Minutes, Seconds
        self.end_time = [18,41,00] # Hours, Minutes, Seconds

        self.timer_sched_time = 5 # seconds

        threading.Thread(name="time_checker", target=self.check_time, args=(self.start_time, self.end_time,)).start()
        threading.Thread(name="scheduled_job", target=self.Timer, args=(self.timer_sched_time, )).start()

        while True:
            time.sleep(10)

Переменная run_permission является логическим значением, используемым в качестве флага для проверки возможности выполнения задания в таймере.

Переменная start_time задает время начала дляcheck_time подпрограмма, которая записывает переменную run_permission в True, если время большое или равно start_time

Переменная end_time устанавливает время остановки для подпрограммы check_time, которая записываетпеременная run_permission имеет значение False, если время большое или равно end_time

Переменная timer_sched_time устанавливает задержку для таймера, задержка необходима для вычисления времени ожидания, она предоставляетидеальное время выполнения каждые 5 секунд: 17.00.00 - 17.00.05 - 17.00.10 - 17.00.15 и т. д. и т. д.

Этодве строки запускают потоки для задания check_time и задания Timer:

threading.Thread(name="time_checker", target=self.check_time, args=(self.start_time, self.end_time,)).start()
threading.Thread(name="scheduled_job", target=self.Timer, args=(self.timer_sched_time, )).start()

Эти две строки поддерживают работу основного потока, но спят основной поток, чтобы уменьшитьпотребление ресурсов:

while True:
    time.sleep(10)

Функция timer_job просто печатает время в формате Unix и удобочитаемом формате:

def timer_job(self, unix_time, human_time):
        print "Unix time: %s  Human time: %s \n" % (unix_time, human_time)

Для перевода формата Unix вы можете использовать веб-сайт epoch converter .

Функция Timer вычисляет время для сна, чтобы предоставить выполнение идеального времени, берет временную метку в формате unix и human и передает ее в timer_job если для переменной run_permission установлено значение True:

def Timer(self, delay):
        while True:
            try:
                time_remaining = delay-time.time()%delay
                time.sleep(time_remaining)

                unix_time = str(int(round(time.time()*1000)))
                human_time = str(dt.now())

                if(self.run_permission):
                    self.timer_job(unix_time, human_time)

            except Exception, ex:
                raise ex

Функция check_time использует аргументы start_execution _time и end_execution_time для установки переменной run_permission в True или False если соблюдаются условия выполнения времени (например, если соблюдается диапазон часов / минут / секунд):

def check_time(self, start_execution_time, end_execution_time):
        while True:
            now = dt.now()

            if(now.hour >= start_execution_time[0] and now.minute >= start_execution_time[1] and now.second >= start_execution_time[2]):
                self.run_permission = True

            if(now.hour >= end_execution_time[0] and now.minute >= end_execution_time[1] and now.second >= end_execution_time[2]):
                self.run_permission = False

Как уже говорилось ранее, test() в конце файла вызывает тестовый класс иинициализировать программу, используя __init__ function.

0 голосов
/ 22 февраля 2019

Есть несколько проблем с этим кодом.Во-первых, при зацикливании внутри потока и отсутствии условий, добавьте спящий режим для экономии использования ЦП.Во-вторых, поскольку потоки не являются детерминированными, вы не можете запускать условия на точных временных отметках.Например, поток может пропустить свое выполнение в течение «горячего» интервала времени, и условие никогда не сработает.

Поэтому вы можете вместо этого проверить, прошла ли текущая временная метка определенную временную метку (и насколько), и /или иным образом сравнивайте временные метки.

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

mythrd =threading.Timer(5.0, run_check)

, а затем

mythrd.start()  # will start threading.Timer(5.0, run_check)

Таким образом, когда срабатывает условие now().hour == 16 and now().minute == 30 and now().second == 30, поток запускает другой экземпляр самого себя.Этот экземпляр может запускать другой экземпляр и т. Д. ...

Вы хотели реализовать поток триггера, выполняя run_check обязанности, но затем запустить другой поток, выполняющий фактическую работу?

Вотрешение:

from threading import Thread, Timer
import time
import datetime

keep_checking = True
keep_working = True

def worker_thread():
    while keep_working:
        pass #do my stuff here and remember to use an eventual sleep

def time_checker():
    while keep_checking:
        now = datetime.now()
        if now.hour == 16 and now.minute == 30 and (
           now.second >= 30 and now.second < 31) and (
           not mythrd.isAlive()):
            mythrd.start()
        elif now.minute >= 31 and mythrd.isAlive():
            keep_working = False # and let it die instead to kill it
        else:
            time.sleep(1) # no operation

mythrd = threading.Thread(target=worker_thread)
time_checker() # might turn this into a thread as well

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

...