class SayulitaMain(threading.Thread): def __init__(self): threading.Thread.__init__(self) self.speaker = Synthetizer("festival", "spanish") self.scheduler = Scheduler() self.scheduler.start() def initialization(self): self.speaker.speechit("Aqui proyecto Sayulita operado por x e uno gol yanqui quebec") self.speaker.speechit("Estacion experimental de texto a voz") def features(self): self.clock = Clock() self.news = FeedParserRss() def logging(self, command): if command == 'start': logging.basicConfig(filename='sayulita.log', filemode='w', level=logging.INFO) logging.basicConfig(format='%(asctime)s %(message)s') logging.info('Started') def scheduling(self): #self.scheduler.interval_schedule(seconds=1) #self.clock.clockget() self.news.getitems self.scheduler.add_cron_job(self.clock.clockget,month='*',day='*',hour='*',minute ='*',second='0') self.scheduler.add_cron_job(self.initialization,month='*',day='*',hour='*',minute ='*',second='15') self.scheduler.add_cron_job(self.news.getitems,month='*',day='*',hour='*',minute ='15,30,45',second='15') self.scheduler.print_jobs()
def handle(self, *args, **options): sched = Scheduler(daemonic=True) sched.add_cron_job(job_function, minute='*') sched.configure() try: sched.start() except (KeyboardInterrupt, SystemExit): pass print sched.print_jobs()
def restart_file_schedule(): scheduler = Scheduler(daemonic = False) scheduler.print_jobs() #scheduler.remove_jobstore('file',close=True) #scheduler.shutdown(wait=False) scheduler.add_jobstore(ShelveJobStore('/tmp/db_schedule'), 'file') scheduler.start() print 'success!' scheduler.print_jobs()
def main(): d = date.today() t = time(00,30) startDate = datetime.combine(d,t) startDate = startDate.replace(tzinfo=tz.tzutc()) startDate = startDate.astimezone(tz.tzlocal()) timeStr = startDate.strftime("%Y-%m-%d %H:%M:%S") print timeStr startDate = datetime.strptime(timeStr, "%Y-%m-%d %H:%M:%S") if (datetime.now() - startDate) > timedelta(seconds=1): startDate = startDate + timedelta(days=1) sched = Scheduler() sched.start() sched.add_interval_job(runDateDump, days=1, start_date=startDate.strftime("%Y-%m-%d %H:%M:%S")) sched.print_jobs() while True: sleep(1) print "." atexit.register(lambda: sched.shutdown(wait=True))
def start_schedule(): #if __name__ == '__main__': scheduler_pl = Scheduler(daemonic = False) scheduler_pl.print_jobs() scheduler_pl.shutdown() scheduler_pl.add_jobstore(ShelveJobStore('/tmp/db_pl_schedule'), 'file') v_current_jobs = scheduler_pl.get_jobs() print v_current_jobs if v_current_jobs: # 如果job存在的话,先请客 scheduler_pl.unschedule_func(upload_processlist) scheduler_pl.add_interval_job(upload_processlist, minutes=1) scheduler_pl.start() print 'success!' scheduler_pl.print_jobs() '''
JOBS_DATABASE = "postgresql://*****:*****@localhost/test_jobs" # Start the scheduler sched = Scheduler() sched.add_jobstore(SQLAlchemyJobStore(url=JOBS_DATABASE, tablename='apscheduler_jobs'), 'default') sched.start() def print_reservation_id(reservation_id): print "====> Reservation id is " + str(reservation_id) if __name__ == '__main__': print "====> Printing jobs..." print sched.print_jobs() now = datetime.datetime.now() start_time = now + datetime.timedelta(seconds=3) later = now + datetime.timedelta(seconds=10) print "====> now is " + str(now) print "====> start_time is " + str(start_time) print "====> later is " + str(later) reservation_id = 1 job_name = "print_reservation_id_" + str(reservation_id) print "====> adding start_time job"
class PyFlowScheduler(object): """ This object schedules the submission of the tasks in an :class:`Flow`. There are two types of errors that might occur during the execution of the jobs: #. Python exceptions #. Abinit Errors. Python exceptions are easy to detect and are usually due to a bug in abinitio or random errors such as IOError. The set of Abinit Errors is much much broader. It includes wrong input data, segmentation faults, problems with the resource manager, etc. Abinitio tries to handle the most common cases but there's still a lot of room for improvement. Note, in particular, that `PyFlowScheduler` will shutdown automatically if #. The number of python exceptions is > MAX_NUM_PYEXC #. The number of Abinit Errors (i.e. the number of tasks whose status is S_ERROR) is > MAX_NUM_ERRORS #. The number of jobs launched becomes greater than (SAFETY_RATIO * total_number_of_tasks). #. The scheduler will send an email to the user (specified by mailto) every REMINDME_S seconds. If the mail cannot be sent, it will shutdown automatically. This check prevents the scheduler from being trapped in an infinite loop. """ # Configuration file. YAML_FILE = "scheduler.yml" USER_CONFIG_DIR = os.path.join(os.getenv("HOME"), ".abinit", "abipy") DEBUG = 0 Error = PyFlowSchedulerError def __init__(self, **kwargs): """ Args: weeks: number of weeks to wait days: number of days to wait hours: number of hours to wait minutes: number of minutes to wait seconds: number of seconds to wait verbose: (int) verbosity level max_njobs_inque: Limit on the number of jobs that can be present in the queue use_dynamic_manager: True if the :class:`TaskManager` must be re-initialized from file before launching the jobs. Default: False max_nlaunch: Maximum number of tasks launched by radpifire (default -1 i.e. no limit) """ # Options passed to the scheduler. self.sched_options = AttrDict( weeks=kwargs.pop("weeks", 0), days=kwargs.pop("days", 0), hours=kwargs.pop("hours", 0), minutes=kwargs.pop("minutes", 0), seconds=kwargs.pop("seconds", 0), #start_date=kwargs.pop("start_date", None), ) if all(not v for v in self.sched_options.values()): raise self.Error("Wrong set of options passed to the scheduler.") self.mailto = kwargs.pop("mailto", None) self.verbose = int(kwargs.pop("verbose", 0)) self.use_dynamic_manager = kwargs.pop("use_dynamic_manager", False) self.max_njobs_inqueue = kwargs.pop("max_njobs_inqueue", 200) self.REMINDME_S = float(kwargs.pop("REMINDME_S", 4 * 24 * 3600)) self.MAX_NUM_PYEXCS = int(kwargs.pop("MAX_NUM_PYEXCS", 0)) self.MAX_NUM_ABIERRS = int(kwargs.pop("MAX_NUM_ABIERRS", 0)) self.SAFETY_RATIO = int(kwargs.pop("SAFETY_RATIO", 5)) #self.MAX_ETIME_S = kwargs.pop("MAX_ETIME_S", ) self.max_nlaunch = kwargs.pop("max_nlaunch", -1) if kwargs: raise self.Error("Unknown arguments %s" % kwargs) if has_sched_v3: from apscheduler.schedulers.blocking import BlockingScheduler self.sched = BlockingScheduler() else: from apscheduler.scheduler import Scheduler self.sched = Scheduler(standalone=True) self.nlaunch = 0 self.num_reminders = 1 # Used to keep track of the exceptions raised while the scheduler is running self.exceptions = collections.deque(maxlen=self.MAX_NUM_PYEXCS + 10) # Used to push additional info during the execution. self.history = collections.deque(maxlen=100) @classmethod def from_file(cls, filepath): """Read the configuration parameters from a Yaml file.""" with open(filepath, "r") as fh: return cls(**yaml.load(fh)) @classmethod def from_string(cls, s): """Create an istance from string s containing a YAML dictionary.""" stream = cStringIO(s) stream.seek(0) return cls(**yaml.load(stream)) @classmethod def from_user_config(cls): """ Initialize the :class:`PyFlowScheduler` from the YAML file 'scheduler.yml'. Search first in the working directory and then in the configuration directory of abipy. Raises: RuntimeError if file is not found. """ # Try in the current directory. path = os.path.join(os.getcwd(), cls.YAML_FILE) if os.path.exists(path): return cls.from_file(path) # Try in the configuration directory. path = os.path.join(cls.USER_CONFIG_DIR, cls.YAML_FILE) if os.path.exists(path): return cls.from_file(path) err_msg = "Cannot locate %s neither in current directory nor in %s" % ( cls.YAML_FILE, path) raise cls.Error(err_msg) def __str__(self): """String representation.""" lines = [self.__class__.__name__ + ", Pid: %d" % self.pid] app = lines.append app("Scheduler options: %s" % str(self.sched_options)) app(80 * "=") app(str(self.flow)) return "\n".join(lines) @property def pid(self): """The pid of the process associated to the scheduler.""" try: return self._pid except AttributeError: self._pid = os.getpid() return self._pid @property def pid_file(self): """ Absolute path of the file with the pid. The file is located in the workdir of the flow """ return self._pid_file @property def flow(self): """`Flow`.""" return self._flow @property def num_excs(self): """Number of exceptions raised so far.""" return len(self.exceptions) def get_delta_etime(self): """Returns a `timedelta` object representing with the elapsed time.""" return timedelta(seconds=(time.time() - self.start_time)) def add_flow(self, flow): """Add an :class:`Flow` flow to the scheduler.""" if hasattr(self, "_flow"): raise self.Error("Only one flow can be added to the scheduler.") pid_file = os.path.join(flow.workdir, "_PyFlowScheduler.pid") if os.path.isfile(pid_file): flow.show_status() err_msg = (""" pid_file %s already exists There are two possibilities: 1) There's an another instance of PyFlowScheduler running 2) The previous scheduler didn't exit in a clean way To solve case 1: Kill the previous scheduler (use 'kill pid' where pid is the number reported in the file) Then you can restart the new scheduler. To solve case 2: Remove the pid_file and restart the scheduler. Exiting""" % pid_file) raise self.Error(err_msg) with open(pid_file, "w") as fh: fh.write(str(self.pid)) self._pid_file = pid_file self._flow = flow def start(self): """ Starts the scheduler in a new thread. Returns True if success. In standalone mode, this method will block until there are no more scheduled jobs. """ self.history.append("Started on %s" % time.asctime()) self.start_time = time.time() if has_sched_v3: self.sched.add_job(self.callback, "interval", **self.sched_options) else: self.sched.add_interval_job(self.callback, **self.sched_options) errors = self.flow.look_before_you_leap() if errors: print(errors) self.exceptions.append(errors) return False # Try to run the job immediately. If something goes wrong return without initializing the scheduler. self._runem_all() if self.exceptions: self.cleanup() self.send_email( msg= "Error while trying to run the flow for the first time!\n %s" % self.exceptions) return False self.sched.start() return True def _runem_all(self): """ This function checks the status of all tasks, tries to fix tasks that went unconverged, abicritical, or queuecritical and tries to run all the tasks that can be submitted.+ """ excs = [] flow = self.flow # Allow to change the manager at run-time if self.use_dynamic_manager: from pymatgen.io.abinitio.tasks import TaskManager new_manager = TaskManager.from_user_config() for work in flow: work.set_manager(new_manager) nqjobs = flow.get_njobs_in_queue() if nqjobs is None: nqjobs = 0 print('Cannot get njobs_inqueue') if nqjobs >= self.max_njobs_inqueue: print("Too many jobs in the queue, returning") return if self.max_nlaunch == -1: max_nlaunch = self.max_njobs_inqueue - nqjobs else: max_nlaunch = min(self.max_njobs_inqueue - nqjobs, self.max_nlaunch) # check status flow.check_status() flow.show_status() # fix problems # Try to restart the unconverged tasks # todo donot fire here but prepare for fireing in rapidfire for task in self.flow.unconverged_tasks: try: logger.info("Flow will try restart task %s" % task) fired = task.restart() if fired: self.nlaunch += 1 max_nlaunch -= 1 if max_nlaunch == 0: print("Restart: too many jobs in the queue, returning") flow.pickle_dump() return except Exception: excs.append(straceback()) # move here from withing rapid fire ... # fix only prepares for restarting, and sets to ready flow.fix_critical() # update database flow.pickle_dump() #if self.num_restarts == self.max_num_restarts: # info_msg = "Reached maximum number of restarts. Cannot restart anymore Returning" # logger.info(info_msg) # self.history.append(info_msg) # return 1 # Submit the tasks that are ready. try: nlaunch = PyLauncher(flow).rapidfire(max_nlaunch=max_nlaunch, sleep_time=10) self.nlaunch += nlaunch if nlaunch: print("[%s] Number of launches: %d" % (time.asctime(), nlaunch)) except Exception: excs.append(straceback()) flow.show_status() if excs: logger.critical("*** Scheduler exceptions:\n *** %s" % "\n".join(excs)) self.exceptions.extend(excs) def callback(self): """The function that will be executed by the scheduler.""" try: return self._callback() except: # All exceptions raised here will trigger the shutdown! self.exceptions.append(straceback()) self.shutdown(msg="Exception raised in callback!") def _callback(self): """The actual callback.""" if self.DEBUG: # Show the number of open file descriptors print(">>>>> _callback: Number of open file descriptors: %s" % get_open_fds()) #print('before _runem_all in _callback') self._runem_all() # Mission accomplished. Shutdown the scheduler. all_ok = self.flow.all_ok if self.verbose: print("all_ok", all_ok) if all_ok: self.shutdown( msg= "All tasks have reached S_OK. Will shutdown the scheduler and exit" ) # Handle failures. err_msg = "" # Shall we send a reminder to the user? delta_etime = self.get_delta_etime() if delta_etime.total_seconds() > self.num_reminders * self.REMINDME_S: self.num_reminders += 1 msg = ( "Just to remind you that the scheduler with pid %s, flow %s\n has been running for %s " % (self.pid, self.flow, delta_etime)) retcode = self.send_email(msg, tag="[REMINDER]") if retcode: # Cannot send mail, shutdown now! msg += ( "\nThe scheduler tried to send an e-mail to remind the user\n" + " but send_email returned %d. Aborting now" % retcode) err_msg += msg #if delta_etime.total_seconds() > self.MAX_ETIME_S: # err_msg += "\nExceeded MAX_ETIME_S %s. Will shutdown the scheduler and exit" % self.MAX_ETIME_S # Too many exceptions. Shutdown the scheduler. if self.num_excs > self.MAX_NUM_PYEXCS: msg = "Number of exceptions %s > %s. Will shutdown the scheduler and exit" % ( self.num_excs, self.MAX_NUM_PYEXCS) err_msg += boxed(msg) # Paranoid check: disable the scheduler if we have submitted # too many jobs (it might be due to some bug or other external reasons # such as race conditions between difference callbacks!) if self.nlaunch > self.SAFETY_RATIO * self.flow.num_tasks: msg = "Too many jobs launched %d. Total number of tasks = %s, Will shutdown the scheduler and exit" % ( self.nlaunch, self.flow.num_tasks) err_msg += boxed(msg) # Count the number of tasks with status == S_ERROR. if self.flow.num_errored_tasks > self.MAX_NUM_ABIERRS: msg = "Number of tasks with ERROR status %s > %s. Will shutdown the scheduler and exit" % ( self.flow.num_errored_tasks, self.MAX_NUM_ABIERRS) err_msg += boxed(msg) # Count the number of tasks with status == S_UNCONVERGED. #if self.flow.num_unconverged_tasks: # # TODO: this is needed to avoid deadlocks, automatic restarting is not available yet # msg = ("Found %d unconverged tasks." # "Automatic restarting is not available yet. Will shutdown the scheduler and exit" # % self.flow.num_unconverged_tasks) # err_msg += boxed(msg) #deadlocks = self.detect_deadlocks() #if deadlocks: # msg = ("Detected deadlocks in flow. Will shutdown the scheduler and exit" # % self.flow.num_unconverged_tasks) # err_msg += boxed(msg) if err_msg: # Something wrong. Quit self.shutdown(err_msg) return len(self.exceptions) def cleanup(self): """Cleanup routine: remove the pid file and save the pickle database""" try: os.remove(self.pid_file) except OSError: logger.critical("Could not remove pid_file") pass # Save the final status of the flow. self.flow.pickle_dump() def shutdown(self, msg): """Shutdown the scheduler.""" try: self.cleanup() #if False and self.flow.has_db: # try: # self.flow.db_insert() # except Exception: # logger.critical("MongoDb insertion failed.") self.history.append("Completed on %s" % time.asctime()) self.history.append("Elapsed time %s" % self.get_delta_etime()) if self.DEBUG: print(">>>>> shutdown: Number of open file descriptors: %s" % get_open_fds()) retcode = self.send_email(msg) if self.DEBUG: print("send_mail retcode", retcode) # Write file with the list of exceptions: if self.exceptions: dump_file = os.path.join(self.flow.workdir, "_exceptions") with open(dump_file, "w") as fh: fh.writelines(self.exceptions) fh.write("Shutdown message:\n%s" % msg) finally: # Shutdown the scheduler thus allowing the process to exit. print('this should be the shutdown of the scheduler') # Unschedule all the jobs before calling shutdown self.sched.print_jobs() for job in self.sched.get_jobs(): self.sched.unschedule_job(job) self.sched.print_jobs() self.sched.shutdown() # Uncomment the line below if shutdown does not work! #os.system("kill -9 %d" % os.getpid()) def send_email(self, msg, tag=None): """ Send an e-mail before completing the shutdown. Returns 0 if success. """ try: return self._send_email(msg, tag) except: self.exceptions.append(straceback()) return -2 def _send_email(self, msg, tag): if self.mailto is None: return -1 header = msg.splitlines() app = header.append app("Submitted on %s" % time.ctime(self.start_time)) app("Completed on %s" % time.asctime()) app("Elapsed time %s" % str(self.get_delta_etime())) app("Number of errored tasks: %d" % self.flow.num_errored_tasks) app("Number of unconverged tasks: %d" % self.flow.num_unconverged_tasks) strio = cStringIO() strio.writelines("\n".join(header) + 4 * "\n") # Add the status of the flow. self.flow.show_status(stream=strio) if self.exceptions: # Report the list of exceptions. strio.writelines(self.exceptions) if tag is None: tag = " [ALL OK]" if self.flow.all_ok else " [WARNING]" return sendmail(subject=self.flow.name + tag, text=strio.getvalue(), mailto=self.mailto)
class PyFlowScheduler(object): """ This object schedules the submission of the tasks in an `AbinitFlow`. There are two types of errors that might occur during the execution of the jobs: #. Python exceptions #. Abinit Errors. Python exceptions are easy to detect and are usually due to a bug in abinitio or random errors such as IOError. The set of Abinit Errors is much much broader. It includes wrong input data, segmentation faults, problems with the resource manager, etc. Abinitio tries to handle the most common cases but there's still a lot of room for improvement. Note, in particular, that `PyFlowScheduler` will shutdown automatically if #. The number of python exceptions is > MAX_NUM_PYEXC #. The number of Abinit Errors (i.e. the number of tasks whose status is S_ERROR) is > MAX_NUM_ERRORS #. The number of jobs launched becomes greater than (SAFETY_RATIO * total_number_of_tasks). #. The scheduler will send an email to the user (specified by mailto) every REMINDME_S seconds. If the mail cannot be sent, it will shutdown automatically. This check prevents the scheduler from being trapped in an infinite loop. """ # Configuration file. YAML_FILE = "scheduler.yml" USER_CONFIG_DIR = os.path.join(os.getenv("HOME"), ".abinit", "abipy") DEBUG = 0 Error = PyFlowSchedulerError def __init__(self, **kwargs): """ Args: weeks: number of weeks to wait days: number of days to wait hours: number of hours to wait minutes: number of minutes to wait seconds: number of seconds to wait verbose: (int) verbosity level max_njobs_inque: Limit on the number of jobs that can be present in the queue use_dynamic_manager: True if the task manager must be re-initialized from file before launching the jobs. Default: False max_nlaunch: Maximum number of tasks launched by radpifire (default -1 i.e. no limit) """ # Options passed to the scheduler. self.sched_options = AttrDict( weeks=kwargs.pop("weeks", 0), days=kwargs.pop("days", 0), hours=kwargs.pop("hours", 0), minutes=kwargs.pop("minutes", 0), seconds=kwargs.pop("seconds", 0), #start_date=kwargs.pop("start_date", None), ) if all(not v for v in self.sched_options.values()): raise self.Error("Wrong set of options passed to the scheduler.") self.mailto = kwargs.pop("mailto", None) self.verbose = int(kwargs.pop("verbose", 0)) self.use_dynamic_manager = kwargs.pop("use_dynamic_manager", False) self.max_njobs_inqueue = kwargs.pop("max_njobs_inqueue", 200) self.REMINDME_S = float(kwargs.pop("REMINDME_S", 4 * 24 * 3600)) self.MAX_NUM_PYEXCS = int(kwargs.pop("MAX_NUM_PYEXCS", 0)) self.MAX_NUM_ABIERRS = int(kwargs.pop("MAX_NUM_ABIERRS", 0)) self.SAFETY_RATIO = int(kwargs.pop("SAFETY_RATIO", 5)) #self.MAX_ETIME_S = kwargs.pop("MAX_ETIME_S", ) self.max_nlaunch = kwargs.pop("max_nlaunch", -1) if kwargs: raise self.Error("Unknown arguments %s" % kwargs) if has_sched_v3: from apscheduler.schedulers.blocking import BlockingScheduler self.sched = BlockingScheduler() else: from apscheduler.scheduler import Scheduler self.sched = Scheduler(standalone=True) self.nlaunch = 0 self.num_reminders = 1 # Used to keep track of the exceptions raised while the scheduler is running self.exceptions = collections.deque(maxlen=self.MAX_NUM_PYEXCS + 10) # Used to push additional info during the execution. self.history = collections.deque(maxlen=100) @classmethod def from_file(cls, filepath): """Read the configuration parameters from a Yaml file.""" with open(filepath, "r") as fh: return cls(**yaml.load(fh)) @classmethod def from_string(cls, s): """Create an istance from string s containing a YAML dictionary.""" stream = cStringIO(s) stream.seek(0) return cls(**yaml.load(stream)) @classmethod def from_user_config(cls): """ Initialize the `PyFlowScheduler` from the YAML file 'scheduler.yml'. Search first in the working directory and then in the configuration directory of abipy. Raises: RuntimeError if file is not found. """ # Try in the current directory. path = os.path.join(os.getcwd(), cls.YAML_FILE) if os.path.exists(path): return cls.from_file(path) # Try in the configuration directory. path = os.path.join(cls.USER_CONFIG_DIR, cls.YAML_FILE) if os.path.exists(path): return cls.from_file(path) err_msg = "Cannot locate %s neither in current directory nor in %s" % (cls.YAML_FILE, path) raise cls.Error(err_msg) def __str__(self): """String representation.""" lines = [self.__class__.__name__ + ", Pid: %d" % self.pid] app = lines.append app("Scheduler options: %s" % str(self.sched_options)) app(80 * "=") app(str(self.flow)) return "\n".join(lines) @property def pid(self): """The pid of the process associated to the scheduler.""" try: return self._pid except AttributeError: self._pid = os.getpid() return self._pid @property def pid_file(self): """ Absolute path of the file with the pid. The file is located in the workdir of the flow """ return self._pid_file @property def flow(self): """`AbinitFlow`.""" return self._flow @property def num_excs(self): """Number of exceptions raised so far.""" return len(self.exceptions) def get_delta_etime(self): """Returns a `timedelta` object representing with the elapsed time.""" return timedelta(seconds=(time.time() - self.start_time)) def add_flow(self, flow): """Add an `AbinitFlow` flow to the scheduler.""" if hasattr(self, "_flow"): raise self.Error("Only one flow can be added to the scheduler.") pid_file = os.path.join(flow.workdir, "_PyFlowScheduler.pid") if os.path.isfile(pid_file): flow.show_status() err_msg = (""" pid_file %s already exists There are two possibilities: 1) There's an another instance of PyFlowScheduler running 2) The previous scheduler didn't exit in a clean way To solve case 1: Kill the previous scheduler (use 'kill pid' where pid is the number reported in the file) Then you can restart the new scheduler. To solve case 2: Remove the pid_file and restart the scheduler. Exiting""" % pid_file) raise self.Error(err_msg) with open(pid_file, "w") as fh: fh.write(str(self.pid)) self._pid_file = pid_file self._flow = flow def start(self): """ Starts the scheduler in a new thread. Returns True if success. In standalone mode, this method will block until there are no more scheduled jobs. """ self.history.append("Started on %s" % time.asctime()) self.start_time = time.time() if has_sched_v3: self.sched.add_job(self.callback, "interval", **self.sched_options) else: self.sched.add_interval_job(self.callback, **self.sched_options) errors = self.flow.look_before_you_leap() if errors: print(errors) self.exceptions.append(errors) return False # Try to run the job immediately. If something goes wrong return without initializing the scheduler. self._runem_all() if self.exceptions: self.cleanup() self.send_email(msg="Error while trying to run the flow for the first time!\n %s" % self.exceptions) return False self.sched.start() return True def _runem_all(self): """ This function checks the status of all tasks, tries to fix tasks that went unconverged, abicritical, or queuecritical and tries to run all the tasks that can be submitted.+ """ excs = [] flow = self.flow # Allow to change the manager at run-time if self.use_dynamic_manager: from pymatgen.io.abinitio.tasks import TaskManager new_manager = TaskManager.from_user_config() for work in flow: work.set_manager(new_manager) nqjobs = flow.get_njobs_in_queue() if nqjobs is None: nqjobs = 0 print('Cannot get njobs_inqueue') if nqjobs >= self.max_njobs_inqueue: print("Too many jobs in the queue, returning") return if self.max_nlaunch == -1: max_nlaunch = self.max_njobs_inqueue - nqjobs else: max_nlaunch = min(self.max_njobs_inqueue - nqjobs, self.max_nlaunch) # check status flow.check_status() flow.show_status() # fix problems # Try to restart the unconverged tasks # todo donot fire here but prepare for fireing in rapidfire for task in self.flow.unconverged_tasks: try: logger.info("AbinitFlow will try restart task %s" % task) fired = task.restart() if fired: self.nlaunch += 1 max_nlaunch -= 1 if max_nlaunch == 0: print("Restart: too many jobs in the queue, returning") flow.pickle_dump() return except Exception: excs.append(straceback()) # move here from withing rapid fire ... # fix only prepares for restarting, and sets to ready flow.fix_critical() # update database flow.pickle_dump() #if self.num_restarts == self.max_num_restarts: # info_msg = "Reached maximum number of restarts. Cannot restart anymore Returning" # logger.info(info_msg) # self.history.append(info_msg) # return 1 # Submit the tasks that are ready. try: nlaunch = PyLauncher(flow).rapidfire(max_nlaunch=max_nlaunch, sleep_time=10) self.nlaunch += nlaunch if nlaunch: print("[%s] Number of launches: %d" % (time.asctime(), nlaunch)) except Exception: excs.append(straceback()) flow.show_status() if excs: logger.critical("*** Scheduler exceptions:\n *** %s" % "\n".join(excs)) self.exceptions.extend(excs) def callback(self): """The function that will be executed by the scheduler.""" try: return self._callback() except: # All exceptions raised here will trigger the shutdown! self.exceptions.append(straceback()) self.shutdown(msg="Exception raised in callback!") def _callback(self): """The actual callback.""" if self.DEBUG: # Show the number of open file descriptors print(">>>>> _callback: Number of open file descriptors: %s" % get_open_fds()) #print('before _runem_all in _callback') self._runem_all() # Mission accomplished. Shutdown the scheduler. all_ok = self.flow.all_ok if self.verbose: print("all_ok", all_ok) if all_ok: self.shutdown(msg="All tasks have reached S_OK. Will shutdown the scheduler and exit") # Handle failures. err_msg = "" # Shall we send a reminder to the user? delta_etime = self.get_delta_etime() if delta_etime.total_seconds() > self.num_reminders * self.REMINDME_S: self.num_reminders += 1 msg = ("Just to remind you that the scheduler with pid %s, flow %s\n has been running for %s " % (self.pid, self.flow, delta_etime)) retcode = self.send_email(msg, tag="[REMINDER]") if retcode: # Cannot send mail, shutdown now! msg += ("\nThe scheduler tried to send an e-mail to remind the user\n" + " but send_email returned %d. Aborting now" % retcode) err_msg += msg #if delta_etime.total_seconds() > self.MAX_ETIME_S: # err_msg += "\nExceeded MAX_ETIME_S %s. Will shutdown the scheduler and exit" % self.MAX_ETIME_S # Too many exceptions. Shutdown the scheduler. if self.num_excs > self.MAX_NUM_PYEXCS: msg = "Number of exceptions %s > %s. Will shutdown the scheduler and exit" % ( self.num_excs, self.MAX_NUM_PYEXCS) err_msg += boxed(msg) # Paranoid check: disable the scheduler if we have submitted # too many jobs (it might be due to some bug or other external reasons # such as race conditions between difference callbacks!) if self.nlaunch > self.SAFETY_RATIO * self.flow.num_tasks: msg = "Too many jobs launched %d. Total number of tasks = %s, Will shutdown the scheduler and exit" % ( self.nlaunch, self.flow.num_tasks) err_msg += boxed(msg) # Count the number of tasks with status == S_ERROR. if self.flow.num_errored_tasks > self.MAX_NUM_ABIERRS: msg = "Number of tasks with ERROR status %s > %s. Will shutdown the scheduler and exit" % ( self.flow.num_errored_tasks, self.MAX_NUM_ABIERRS) err_msg += boxed(msg) # Count the number of tasks with status == S_UNCONVERGED. #if self.flow.num_unconverged_tasks: # # TODO: this is needed to avoid deadlocks, automatic restarting is not available yet # msg = ("Found %d unconverged tasks." # "Automatic restarting is not available yet. Will shutdown the scheduler and exit" # % self.flow.num_unconverged_tasks) # err_msg += boxed(msg) #deadlocks = self.detect_deadlocks() #if deadlocks: # msg = ("Detected deadlocks in flow. Will shutdown the scheduler and exit" # % self.flow.num_unconverged_tasks) # err_msg += boxed(msg) if err_msg: # Something wrong. Quit self.shutdown(err_msg) return len(self.exceptions) def cleanup(self): """ Cleanup routine: remove the pid file and save the pickle database """ try: os.remove(self.pid_file) except OSError: logger.critical("Could not remove pid_file") pass # Save the final status of the flow. self.flow.pickle_dump() def shutdown(self, msg): """Shutdown the scheduler.""" try: self.cleanup() #if False and self.flow.has_db: # try: # self.flow.db_insert() # except Exception: # logger.critical("MongoDb insertion failed.") self.history.append("Completed on %s" % time.asctime()) self.history.append("Elapsed time %s" % self.get_delta_etime()) if self.DEBUG: print(">>>>> shutdown: Number of open file descriptors: %s" % get_open_fds()) retcode = self.send_email(msg) if self.DEBUG: print("send_mail retcode", retcode) # Write file with the list of exceptions: if self.exceptions: dump_file = os.path.join(self.flow.workdir, "_exceptions") with open(dump_file, "w") as fh: fh.writelines(self.exceptions) fh.write("Shutdown message:\n%s" % msg) finally: # Shutdown the scheduler thus allowing the process to exit. print('this should be the shutdown of the scheduler') # Unschedule all the jobs before calling shutdown self.sched.print_jobs() for job in self.sched.get_jobs(): self.sched.unschedule_job(job) self.sched.print_jobs() self.sched.shutdown() # Uncomment the line below if shutdown does not work! #os.system("kill -9 %d" % os.getpid()) def send_email(self, msg, tag=None): """ Send an e-mail before completing the shutdown. Returns 0 if success. """ try: return self._send_email(msg, tag) except: self.exceptions.append(straceback()) return -2 def _send_email(self, msg, tag): if self.mailto is None: return -1 header = msg.splitlines() app = header.append app("Submitted on %s" % time.ctime(self.start_time)) app("Completed on %s" % time.asctime()) app("Elapsed time %s" % str(self.get_delta_etime())) app("Number of errored tasks: %d" % self.flow.num_errored_tasks) app("Number of unconverged tasks: %d" % self.flow.num_unconverged_tasks) strio = cStringIO() strio.writelines("\n".join(header) + 4 * "\n") # Add the status of the flow. self.flow.show_status(stream=strio) if self.exceptions: # Report the list of exceptions. strio.writelines(self.exceptions) if tag is None: tag = " [ALL OK]" if self.flow.all_ok else " [WARNING]" return sendmail(subject=self.flow.name + tag, text=strio.getvalue(), mailto=self.mailto)
'-leases', dest='leases', default='/home/router/dnsmasq.leases') parser.add_argument( '-assoclist', dest='assoclist', default='/home/router/assoclist') args = parser.parse_args() if not os.path.isfile(args.leases): logger.debug('Not a file: %s' % args.leases) exit(1) global DATA, OPEN_IMAGE, CLOSE_IMAGE, LEASES_FILENAME, ASSOCLIST_FILENAME ASSOCLIST_FILENAME = args.assoclist LEASES_FILENAME = args.leases OPEN_IMAGE = get_file_content('xcj_open_badge.gif') CLOSE_IMAGE = get_file_content('xcj_closed_badge.gif') DATA = WifiData(client()) update_macs() update_leases() update_excluded() SCHED.start() SCHED.print_jobs() logger.info('Starting API server') run(host='0.0.0.0', reloader=True, port=9000, debug=True)
class Controller: def __init__(self): # Start the scheduler self.sched = Scheduler() self.sched.start() # set default turn on and turn off times # default to everyday self.daysLabel=dayLabels[0] self.days=dayOptions[self.daysLabel] # turn on at 7am self.turnOnHour = 7 self.turnOnMin = 0 self.DisplayOnJob = self.sched.add_cron_job(self.displayPowerOn, day_of_week=self.days, hour=self.turnOnHour, minute=self.turnOnMin) # turn off at 7pm self.turnOffHour = 19 self.turnOffMin = 0 self.DisplayOffJob = self.sched.add_cron_job(self.displayPowerOff, day_of_week=self.days, hour=self.turnOffHour, minute=self.turnOffMin) # print the menu self.printMenu() def printMenu(self): print(""" Timer Test Menu 1. Set Turn On/Off Days 2. Set Turn On Time 3. Set Turn Off Time 4. Get On-Off Times 5. Quit/Exit """) # get the selection self.main_selection = input("Please select: ") print("\n") if self.main_selection == '1': print('Current Turn On/Off days:',self.daysLabel) print('1. Daily') print('2. WeekDays') self.newDays = input("Select which days to use: ") # validate entry if int(self.newDays)==1 or int(self.newDays)==2: self.daysLabel = dayLabels[int(self.newDays)-1] self.days = dayOptions[self.daysLabel] # cancel old jobs and start new ones self.schedDisplayOn() self.schedDisplayOff() print('New Turn On/Off days:', self.daysLabel) else: print('Invalid entry') self.printMenu() elif self.main_selection == '2': print('Current Turn On time ', str(self.turnOnHour), ':', str(self.turnOnMin).zfill(2), sep='') self.newTurnOnHour = input("Enter new turn on hour (in 24 hour clock): ") # validate hour entry if int(self.newTurnOnHour) < 24 and int(self.newTurnOnHour) >= 0: self.newTurnOnMin = input("Enter new turn on minute: ") # validate min entry if int(self.newTurnOnMin) < 60 and int(self.newTurnOnMin) >= 0: # assign new hour self.turnOnHour = int(self.newTurnOnHour) # assign new minute self.turnOnMin = int(self.newTurnOnMin) # cancel old job and start new one self.schedDisplayOn() # print new turn on time print('New Turn On time ', str(self.turnOnHour), ':', str(self.turnOnMin).zfill(2), sep='') else: print('Invalid Turn On Min') else: print('Invalid Turn On Hour') self.printMenu() elif self.main_selection == '3': print('Current Turn Off time ', str(self.turnOffHour), ':', str(self.turnOffMin).zfill(2), sep='') self.newTurnOffHour = input("Enter new turn off hour (in 24 hour clock): ") # validate hour entry if int(self.newTurnOffHour) < 24 and int(self.newTurnOffHour) >= 0: self.newTurnOffMin = input("Enter new turn off minute: ") # validate min entry if int(self.newTurnOffMin) < 60 and int(self.newTurnOffMin) >= 0: # assign new hour self.turnOffHour = int(self.newTurnOffHour) # assign new minute self.turnOffMin = int(self.newTurnOffMin) # cancel old job and start new one self.schedDisplayOff() # print new turn off time print('New Turn Off time ', str(self.turnOffHour), ':', str(self.turnOffMin).zfill(2), sep='') else: print('Invalid Turn Off Min') else: print('Invalid Turn Off Hour') self.printMenu() elif self.main_selection == '4': print('Turn On ',self.daysLabel,' at ',str(self.turnOnHour),':',str(self.turnOnMin).zfill(2), sep='') print('Turn Off ',self.daysLabel,' at ', str(self.turnOffHour), ':', str(self.turnOffMin).zfill(2), sep='') self.sched.print_jobs() self.printMenu() elif self.main_selection == '5': sys.exit() else: print("Invalid selection.\n") self.printMenu() def displayPowerOn(self): print("Display On") def displayPowerOff(self): print("Display Off") def schedDisplayOn(self): # cancel the old job self.sched.unschedule_job(self.DisplayOnJob) # schedule the new job self.DisplayOnJob = self.sched.add_cron_job(self.displayPowerOn, day_of_week=self.days, hour=self.turnOnHour, minute=self.turnOnMin) def schedDisplayOff(self): # cancel the old job self.sched.unschedule_job(self.DisplayOffJob) # schedule the new job self.DisplayOffJob = self.sched.add_cron_job(self.displayPowerOff, day_of_week=self.days, hour=self.turnOffHour, minute=self.turnOffMin)
try: opts, args = getopt(sys.argv[1:], "dp") except GetoptError as err: # print help information and exit: print(str(err)) for flag, value in opts: if flag == '-d': daemon = True if flag == '-p': process = True if daemon: scheduler = Scheduler(standalone=False, daemonic=True) scheduler.add_cron_job(agent.main, month=config['scheduler']['month'], day=config['scheduler']['day'], hour=config['scheduler']['hour'],) scheduler.start() elif process: print("Initializing growpy without scheduler") import time while True: start = time.time() agent.main() print("Threads Time Elapsed: ", time.time() - start) sleep(60) else: print("Initializing Scheduler standalone") scheduler = Scheduler(standalone=True) scheduler.add_cron_job(agent.main, minute='*', day='*', hour='17') scheduler.print_jobs() scheduler.start()
class Sched(Basemodule): # ################################################################################ # initialization of module and optional load of config files # ################################################################################ def __init__(self, instance_queue, global_queue): # # "sched|port|command or action" # self.logger = logging.getLogger('Hasip.sched') self.sched = Scheduler() self.items = ConfigItemReader() self.mod_list = self.items.get_items_dict() # getting module list from item file self.queue_identifier = 'sched' # this is the 'module address' self.instance_queue = instance_queue # worker queue to receive jobs self.global_queue = global_queue # queue to communicate back to main thread self.sched.start() # read jobs configuration self.config = ConfigBaseReader('config/jobs/') if self.config.has_config_files(): # true self.logger.info('Loading config files...') self.jobs = self.config.get_values() else: self.logger.info('No config files present.') self.jobs = [] sched_params={} for section in self.jobs: for item in self.jobs[section]: if self.jobs[section][item] != '': sched_params.update({item : self.jobs[section][item]}) else: sched_params.update({item : None}) self.sched.add_cron_job(self.send_msg, year = sched_params['year'], month = sched_params['month'], day = sched_params['day'], week = sched_params['week'], day_of_week = sched_params['day_of_week'], hour = sched_params['hour'], minute = sched_params['minute'], second = sched_params['second'], args=(sched_params['module'],sched_params['action'])) self.logger.debug(self.sched.print_jobs()) # @TODO loading jobs from persistent store and create them in the scheduler # ################################################################################ # main thread of this module file which runs in background and constanly # checks working queue for new tasks. # ################################################################################ def worker(self): while True: instance_queue_element = self.instance_queue.get(True) _senderport = instance_queue_element.get("module_from_port") _sender = instance_queue_element.get("module_from") _port = instance_queue_element.get("module_addr") _action = instance_queue_element.get("cmd") _optargs = instance_queue_element.get("opt_args") options = { "create" : self.create, "delete" : self.delete } options[_action](_sender, _senderport, _port, _optargs) # ################################################################################ # # "private" methods from here on... # # ################################################################################ def create(self, sender, senderport, port, optargs): # @TODO print "Function to put jobs in the running scheduler job queue and store them persistent" pass def delete(self, sender, senderport, port, optargs): # @TODO print "Function to delete running and persistent jobs" pass def send_msg(self, module, action): # ######################################## if module in self.mod_list.keys(): # checking existence of requested module rcpt = self.mod_list[module][0] # setting receiving module from item file mid = self.mod_list[module][1] # setting module id from item file msg = { # creating queue message 'module_from_port': 0, # ######################################## 'module_from': 'sched', 'module_rcpt': rcpt, 'module_addr': mid, 'cmd': action, 'opt_args': '' } self.global_queue.put(msg)
mC(auth['account_sid'],auth['auth_token'],targetNumber,ngrokURL) print "Call Queued Up" time.sleep(60) # Twilio default call timeout is 60 sec #kill = raw_input("Kill proceses? (y/n):") #while kill in ['n']: # kill = raw_input("Kill proceses? (y/n):") print "Killing processes" ngrok.kill() # kill ngrok process os.system('killall -KILL Python') # kill web server and this thread # Start the scheduler sched = Scheduler() sched.start() # Convert UTC target to local time localTarget = utc2local(datetime.strptime(targetTimeUTC,'%Y-%m-%d %H:%M:%S')) job = sched.add_date_job(main, localTarget, [filename,targetNumber,ngrokURL]) sched.print_jobs() print 'Current time is %s' % datetime.now() # Keep scheduler alive until you hit Ctrl+C! while True: time.sleep(1) sched.shutdown()
class ServiceManager(object): def __init__(self, irlp): self.irlp = irlp self.pidfile = None self.scheduler_status = False self.pidfile = "/tmp/nuupxe.pid" def __del__(self): pass def voicesynthetizer(self): self.voicesynthetizer = VoiceSynthetizer("google", "spanish") def voicesynthetizerget(self): return self.voicesynthetizer def modules_setup(self): # Production Modules self.aprstracker = AprsTracker(self.voicesynthetizer) self.aprstt = Aprstt(self.voicesynthetizer) self.clock = Clock(self.voicesynthetizer) self.identification = Identification(self.voicesynthetizer) self.meteorology = Meteorology(self.voicesynthetizer) self.news = News(self.voicesynthetizer) self.selfie = Selfie(self.voicesynthetizer) self.voicecommand = VoiceCommand(self.voicesynthetizer) self.voicemail = VoiceMail(self.voicesynthetizer) self.weather = Weather(self.voicesynthetizer) self.wolframalpha = WolframAlpha(self.voicesynthetizer) # Experimental Modules self.assistant = Assistant(self.voicesynthetizer) self.messages = Messages(self.voicesynthetizer) self.morseteacher = MorseTeacher(self.voicesynthetizer) self.seismology = Seismology(self.voicesynthetizer) self.sstv = SSTV(self.voicesynthetizer) self.voiceapp = VoiceApp(self.voicesynthetizer) self.voiceexperimental = VoiceExperimental(self.voicesynthetizer) self.voicemailer = VoiceMailer(self.voicesynthetizer) def dtmf_setup(self,dtmf): dtmf_codes = { 'PS0' : 'alive', 'PS1' : 'aprstracker', 'PS2' : 'news', 'PS3' : 'meteorology', 'PS4' : 'seismology', 'PS5' : 'selfie', 'PS6' : 'voicecommand', 'PS7' : 'voiceexperimental', 'PS8' : 'wolframalpha', 'PS9' : 'voicemail', 'PS10' : 'sstv', 'PS11' : 'voiceapp', } return dtmf_codes.get(dtmf) def enabled(self): return os.path.isfile(self.pidfile) def enable(self): pid = str(os.getpid()) logging.info('Process Id' + pid) file(self.pidfile, 'w').write(pid) def disable(self): if self.enabled(): os.unlink(self.pidfile) if self.scheduler_status: self.scheduler.shutdown() def bing_mode(self): logging.info('Mode Bing') self.sstv = SSTV(self.voicesynthetizer) self.sstv.download() def observer_mode(self): logging.info('Mode Observer') pub = Publisher(['text', 'voice']) # Radio, Twitter, Email, Telegram, Whatsapp radio = Subscriber('radio') twitter = Subscriber('twitter') email = Subscriber('email') telegram = Subscriber('telegram') pub.register("text", radio) pub.register("voice", radio) pub.register("text", twitter) pub.register("text", email) pub.register("text", telegram) pub.register("voice", telegram) pub.dispatch("text", "this is text") pub.dispatch("voice", "this is voice") def scheduler_mode(self): logging.info('Mode Scheduler') self.voicesynthetizer.speechit("Modo Planificador") self.scheduler = Scheduler(misfire_grace_time=900, coalesce=True, threadpool=ThreadPool(max_threads=1)) self.schedule() self.scheduler.start() self.schedule_print() self.scheduler_status = True while True: time.sleep(5) if self.irlp.active(): time.sleep(5) self.irlp.busy() self.voicesynthetizer.speechit("Se ha activado el nodo, Proyecto NuupXe dice hasta pronto!") break self.disable() def writing_mode(self): logging.info('Mode Writing') # self.voicesynthetizer.speechit("Modo Escritura") while True: print " Type any text to make use of Text to Speech infraestructure" x = raw_input(" Type 'e' for exit: ") if x.lower() == 'e': self.disable() break; else: self.voicesynthetizer.speechit(x) time.sleep(1) def module_mode(self, module, dtmf=None): logging.info('Mode Module ' + module) # Custom Decode Activated Modules if module == 'identification': self.identification = Identification(self.voicesynthetizer) self.identification.identify() elif module == 'date': self.clock = Clock(self.voicesynthetizer) self.clock.date() elif module == 'hour': self.clock = Clock(self.voicesynthetizer) self.clock.hour() elif module == 'temperature': self.weather = Weather(self.voicesynthetizer) self.weather.temperature() elif module == 'weather': self.weather = Weather(self.voicesynthetizer) self.weather.report() # PS Activated Modules elif module == 'alive': alive() elif module == 'aprstracker': self.aprstracker = AprsTracker(self.voicesynthetizer) self.aprstracker.localize() elif module == 'news': self.news = News(self.voicesynthetizer) self.news.getitems() elif module == 'meteorology': self.meteorology = Meteorology(self.voicesynthetizer) self.meteorology.conagua_clima() elif module == 'selfie': self.selfie = Selfie(self.voicesynthetizer) self.selfie.get() elif module == 'voicecommand': self.voicecommand = VoiceCommand(self.voicesynthetizer) self.voicecommand.listen() elif module == 'voiceapp': self.voiceapp = VoiceApp(self.voicesynthetizer) self.voiceapp.application() elif module == 'voicemail': self.voicemail = VoiceMail(self.voicesynthetizer) self.voicemail.run(dtmf) elif module == 'wolframalpha': self.wolframalpha = WolframAlpha(self.voicesynthetizer) self.wolframalpha.ask() # SS Activated Modules # Experimental Modules elif module == 'aprstt': self.aprstt = Aprstt(self.voicesynthetizer) self.aprstt.query(dtmf) elif module == 'seismology': self.seismology = Seismology(self.voicesynthetizer) self.seismology.SismologicoMX() elif module == 'morselearn': self.morseteacher = MorseTeacher(self.voicesynthetizer) self.morseteacher.learn() elif module == 'morsecontest' : self.morseteacher = MorseTeacher(self.voicesynthetizer) self.morseteacher.contest() elif module == 'regulations': self.messages = Messages(self.voicesynthetizer) self.messages.readfile('learning/reglamentos.1') elif module == 'radioclub': self.messages = Messages(self.voicesynthetizer) self.messages.readfile('learning/arej.radioclubs') elif module == 'stations': self.messages = Messages(self.voicesynthetizer) self.messages.stations() elif module == 'sstv': self.sstv = SSTV(self.voicesynthetizer) self.sstv.decode() elif module == 'assistant': self.assistant = Assistant(self.voicesynthetizer) self.assistant.demo1() elif module == 'voicebackground': self.voicecommand = VoiceCommand(self.voicesynthetizer) self.voicecommand.background() elif module == 'voiceexperimental': self.voiceexperimental = VoiceExperimental(self.voicesynthetizer) self.voiceexperimental.listen() elif module == 'voicemailer': self.voicemailer = VoiceMailer(self.voicesynthetizer) self.voicemailer.attend(dtmf) else: self.voicesynthetizer.speechit("No hemos implementado tu comando! Lo siento!") self.disable() def voice_mode(self, text): logging.info('Voice Mode') try: self.voicesynthetizer.speechit(text) except (StopIteration, KeyboardInterrupt, SystemExit): pass def phonetic_mode(self, text): logging.info('Phonetic Mode') phonetic = Phonetic() try: text = ' '.join(phonetic.decode(text)) self.voicesynthetizer.speechit(text) except (StopIteration, KeyboardInterrupt, SystemExit): pass def schedule_print(self): self.scheduler.print_jobs() def schedule(self): # Production Modules self.scheduler.add_cron_job(self.clock.date, month='*', day_of_week='*', hour='06,12,22', minute ='00', second='00') self.scheduler.add_cron_job(self.clock.hour, month='*', day_of_week='*', hour='*', minute ='*/15', second='00') self.scheduler.add_cron_job(self.identification.identify, month='*', day_of_week='*', hour='*', minute ='*/30', second='00') self.scheduler.add_cron_job(self.selfie.get, month='*', day_of_week='*', hour='00,04,08,14,19', minute ='00', second='00') self.scheduler.add_cron_job(self.weather.report, month='*', day_of_week='*', hour='*/2', minute ='00', second='00') # Experimental Modules self.scheduler.add_cron_job(self.seismology.SismologicoMX, month='*', day='*', hour='*/4', minute ='00', second='00') self.scheduler.add_cron_job(self.news.getitems, month='*', day='*', hour='*/4', minute ='00', second='00') self.scheduler.add_cron_job(self.meteorology.conagua_clima, month='*', day='*', hour='*', minute ='15', second='00') self.scheduler.add_cron_job(self.messages.stations, month='*', day='*', hour='*/4', minute ='00', second='00') self.scheduler.add_cron_job(self.sstv.decode, month='*', day='*', hour='00,04,08,14,19', minute ='00', second='00') # Learning Modules, AREJ self.scheduler.add_cron_job(self.messages.readfile,args=['learning/arej.radioclubs'],month='*',day_of_week='*',hour='7,12,17',minute ='00',second='00') # Learning Modules, Morse self.scheduler.add_cron_job(self.morseteacher.learn, month='*', day='*', hour='07,12,17', minute ='30', second='00') self.scheduler.add_cron_job(self.morseteacher.contest, month='*', day='*', hour='07,12,17', minute ='45', second='00') # Learning Modules, Reglamentos self.scheduler.add_cron_job(self.messages.readfile,args=['learning/reglamentos.1'], month='*', day_of_week='mon', hour='08,13,18', minute ='00', second='00') self.scheduler.add_cron_job(self.messages.readfile,args=['learning/reglamentos.2'], month='*', day_of_week='tue', hour='08,13,18', minute ='00', second='00') self.scheduler.add_cron_job(self.messages.readfile,args=['learning/reglamentos.3'], month='*', day_of_week='wed', hour='08,13,18', minute ='00', second='00') self.scheduler.add_cron_job(self.messages.readfile,args=['learning/reglamentos.4'], month='*', day_of_week='thu', hour='08,13,18', minute ='00', second='00') self.scheduler.add_cron_job(self.messages.readfile,args=['learning/reglamentos.5'], month='*', day_of_week='fri', hour='08,13,18', minute ='00', second='00')
board.last_notification = board.last_request board.save() if len(message) > 0: recipients = User.objects.filter( is_staff=True, location__building=building).values_list('email', flat=True) if len(recipients) > 0: send_mail('%s | %s' % (building.title, 'Warnung!'), message, '*****@*****.**', recipients, fail_silently=False) cron.start() cron.print_jobs() @receiver(post_save, sender=User) def create_user_profile(sender, instance, created, **kwargs): from api.models import UserProfile if created: profile, is_new = UserProfile.objects.get_or_create(user=instance) def validate_pdf_file(value): if not value.name.endswith('.pdf'): raise ValidationError(u'Dieses Feld erlaubt nur PDF-Dateien.') def user_unicode(user):
ov.o(3) # always open valve 3 (main valve) time.sleep(3) ov.o(valve) time.sleep(25) if __name__ == "__main__": conf = json.loads(open("/home/pi/garden/python/config.json").read()) ig = IrrigationClient(conf) # Start the scheduler sched = Scheduler() sched.start() for ii in range(len(conf['valve'])): wateringHour = conf['valve'][ii]['wateringHour'] vv = int(conf['valve'][ii]['nr']) print "scheduling", wateringHour, vv logging.info("scheduling {0} {1}".format( wateringHour, vv)) sched.add_cron_job(ig.irrigate,args=[vv], hour = wateringHour, minute=40) ## endless loop ## while True: with open('/home/pi/garden/python/schedlog.log','a') as f: sched.print_jobs(f) time.sleep(1800)
# camera job = scheduler.add_cron_job(useCamera.takeSinglePicture, hour="*", args=['main',50]) # send daily picture job = scheduler.add_cron_job(sendPictureEmail.sendPictureEmail, hour="22",minute="20", args=['main',0]) # restart solar at 22:02 because there is no turbine left! # job = scheduler.add_cron_job(selectSolar.selectSolar, hour="22",minute="02", args=['main',0]) sys.stdout.write('Press Ctrl+C to exit\n') scheduler.start() scheduler.print_jobs() while True: sys.stdout.write('.'); sys.stdout.flush() myDateString = time.strftime("%Y-%m-%d", time.gmtime()) myTimeString = time.strftime("%H:%M:%S", time.gmtime()) print "-%s %s-" % (myDateString, myTimeString) print ("hasBW=", hasBWInterrupted) # respond to interrupt #if (hasBWInterrupted == True): #if ((GPIO.event_detected(11) == True) or (hasBWInterrupted == True)): if ((GPIO.input(11) == True) or (hasBWInterrupted == True)): # The routine will be executed now hasBWInterrupted = True; result = recieveInterruptFromBW.recieveInterruptFromBW("test", 1)
def start_schedule(): #if __name__ == '__main__': os_user = config.OS_USER os_password = config.OS_APPS_PASSWD scheduler = Scheduler(daemonic = False) scheduler.print_jobs() #scheduler.remove_jobstore('file',close=True) #scheduler.shutdown(wait=False) scheduler.shutdown() #scheduler.unschedule_func(backup) scheduler.add_jobstore(ShelveJobStore('/tmp/db_schedule'), 'file') v_current_jobs = scheduler.get_jobs() print v_current_jobs if v_current_jobs: # 如果job存在的话,先请客 scheduler.unschedule_func(backup) #scheduler = Scheduler(standalone=True) #scheduler = Scheduler(daemon=True) #连接配置中心库,获取数据库备份周期等信息 db = Connection('/tmp/mysql3306.sock', config.DB_NAME, config.DB_USER, config.DB_PASSWD, time_zone='+8:00') v_sql = r"""SELECT a.instance_id,b.ip,b.port,a.backup_interval_type,a.backup_start_time from mysql_ins_bak_setup a,tag b where a.instance_id=b.id """ print v_sql bak_server_list = db.query(v_sql) if bak_server_list: # 有server需要配置 i=0 # 把还没有开始的调度任务,置为手工结束 backup_result_type=4 v_manual_end_sql = 'update mysql_ins_bak_log set backup_result_type=4 where backup_result_type=0' db.execute(v_manual_end_sql) for bak_server in bak_server_list: instance_id = bak_server['instance_id'] from_host = bak_server['ip'] #print from_host mysql_port = bak_server['port'] backup_interval_type = bak_server['backup_interval_type'] backup_start_time = bak_server['backup_start_time'] str_start_date= time.strftime("%Y-%m-%d") + ' ' + backup_start_time print str_start_date if backup_interval_type == 1: # every day #内存jobstore #scheduler.add_interval_job(backup, days=1, start_date=str_start_date, args=[from_host, mysql_port, os_user, os_password]) #文件jobstore jobstore='file' scheduler.add_interval_job(backup, days=1, start_date=str_start_date, args=[from_host, mysql_port, os_user, os_password], jobstore='file') #scheduler.add_interval_job(backup, days=1, start_date='2014-07-18 18:17:01', args=[from_host, mysql_port, os_user, os_password]) elif backup_interval_type == 2: # every week scheduler.add_interval_job(backup, weeks=1, start_date=str_start_date, args=[from_host, mysql_port, os_user, os_password]) elif backup_interval_type == 3: # every hour scheduler.add_interval_job(backup, hours=1, start_date=str_start_date, args=[from_host, mysql_port, os_user, os_password]) # 开始在数据库记录备份的调度任务状态 0:调度任务已启动,实际备份还没有开始 v_sche_start_sql = """insert into mysql_ins_bak_log(instance_id,backup_result_type) values(%d,0)""" % (instance_id) db.execute(v_sche_start_sql) i=i+1 db.close() if bak_server_list: # 有server需要配置 scheduler.start() print 'success!' scheduler.print_jobs() '''
class HMScheduler( Base ): ''' The HMSceduler is used to periodically to send messages to HouseMonitor. The commands can anything including: # Report status # Turn on and off devices. You control the scheduler by sending messages to the scheduler using pubsub. ''' ''' The queue that is used to send messages to the rest of the system. ''' __input_queue = None ''' The scheduler object ''' scheduler = None ''' A dictionary of the current jobs that are running ''' jobs = defaultdict( list ) previous_datetime = datetime.utcnow() def __init__( self, queue ): ''' Initialize the MHScheduler. # Store the queue into __input_queue # Associate **add_interval** with Constants.TopicNames.SchedulerAddIntervalStep # Associate **add_cron** with Constants.TopicNames.SchedulerAddCronStep # Associate **add_date** with Constants.TopicNames.SchedulerAddDateStep # Associate **add_one_shot with Constants.TopicNames.SchedulerAddOneShotStepSchedulerAddOneShotStep # Associate **delete_job** with Constants.TopicNames.SchedulerDeleteJob ''' super( HMScheduler, self ).__init__() self.__input_queue = queue pub.subscribe( self.add_interval, Constants.TopicNames.SchedulerAddIntervalStep ) pub.subscribe( self.add_cron, Constants.TopicNames.SchedulerAddCronStep ) pub.subscribe( self.add_date, Constants.TopicNames.SchedulerAddDateStep ) pub.subscribe( self.add_one_shot, Constants.TopicNames.SchedulerAddOneShotStep ) pub.subscribe( self.deleteJob, Constants.TopicNames.SchedulerDeleteJob ) pub.subscribe( self.print_jobs, Constants.TopicNames.SchedulerPrintJobs ) @property def scheduler_topic_name( self ): ''' The topic name to which this routine subscribes.''' return Constants.TopicNames.SchedulerStep @property def logger_name( self ): ''' Set the logger level. ''' return Constants.LogKeys.Scheduler def start( self ): ''' Start the Scheduler. For more information on the parameter see: .. seealso:: http://packages.python.org/APScheduler/#starting-the-scheduler ''' self.logger.debug( 'Scheduler starting' ) self.scheduler = Scheduler() # self.logger.debug( 'Setting jobstore to HouseMonitor.db' ) # self.scheduler.add_jobstore(ShelveJobStore('HouseMonitor.db'), 'shelve') self.scheduler.start() name = 'scheduled status check' device = 'status' port = 'scheduler' listeners = [Constants.TopicNames.Statistics, Constants.TopicNames.CurrentValueStep] scheduler_id = str( uuid.uuid4() ) args = name, device, port, listeners, scheduler_id self.scheduler.add_interval_job( self.sendCommand, minutes=10, args=args ) name = 'uptime' device = 'HouseMonitor' port = 'uptime' listeners = [Constants.TopicNames.UpTime, Constants.TopicNames.CurrentValueStep] scheduler_id = str( uuid.uuid4() ) args = name, device, port, listeners, scheduler_id self.scheduler.add_interval_job( self.sendCommand, seconds=5, args=args ) name = 'Pulse' device = '0x13a20040902a02' port = 'DIO-0' listeners = [ Constants.TopicNames.StatusPanel_SystemCheck, Constants.TopicNames.ZigBeeOutput] scheduler_id = str( uuid.uuid4() ) args = name, device, port, listeners, scheduler_id self.scheduler.add_interval_job( self.sendCommand, seconds=5, args=args ) def add_interval( self, weeks=0, days=0, hours=0, minutes=0, seconds=0, start_date=None, args=None, kwargs=None ): ''' Schedule an interval at which sendCommand will be called. For more information on the parameter see: .. seealso:: http://packages.python.org/APScheduler/intervalschedule.html :param name: the name of the job to start. This will be used to identify the job if there is a need to delete it latter. :type name: str :param weeks: the number of weeks between calls. :type weeks: int :param days: the number of days between calls. :type days: int :param hours: the number of hours between calls. :type hours: int :param minutes: the number of minutes between calls. :type minutes: int :param seconds: the number of seconds between calls. :type seconds: int :param start_date: the time and date to start the interval. :type start_date: datetime :param args: the args to pass to sendCommand :param kwargs: the kwargs to pass to sendCommand :raises: None ''' name = args[0] self.logger.debug( 'interval ({}) add {} {} {} {} {} {} {}'.format( name, weeks, days, hours, hours, minutes, seconds, start_date ) ) token = self.scheduler.add_interval_job( self.sendCommand, weeks=weeks, days=days, hours=hours, minutes=minutes, seconds=seconds, start_date=start_date, args=args, kwargs=kwargs, name=name ) self.jobs[name].append( token ) def add_cron( self, year=None, month=None, day=None, week=None, day_of_week=None, hour=None, minute=None, second=None, start_date=None, args=None, kwargs=None ): ''' Schedule a cron command to call sendCommand. For more information on the parameter see: .. seealso:: http://packages.python.org/APScheduler/cronschedule.html :param name: the name of the cron job to start. This will be used to identify the job if there is a need to delete it latter. :type weeks: str :param weeks: the number of weeks between calls. :type weeks: int :param days: the number of days between calls. :type days: int :param hours: the number of hours between calls. :type hours: int :param minutes: the number of minutes between calls. :type minutes: int :param seconds: the number of seconds between calls. :type seconds: int :param start_date: the time and date to start the interval. :type start_date: datetime :param args: the args to pass to sendCommand :param kwargs: the kwargs to pass to sendCommand :raises: None ''' name = args[0] self.logger.debug( 'set cron({}) at {}/{}/{} {}:{}:{} {} {} {}'.format( name, year, month, day, hour, minute, second, week, day_of_week, start_date ) ) token = self.scheduler.add_cron_job( self.sendCommand, year=year, month=month, day=day, week=week, day_of_week=day_of_week, hour=hour, minute=minute, second=second, start_date=start_date, args=args, kwargs=kwargs ) self.jobs[name].append( token ) def add_date( self, date, args, **kwargs ): ''' Schedule a specific data and time to call sendCommand. For more information on the parameter see: .. seealso:: http://packages.python.org/APScheduler/dateschedule.html :param name: the name of the cron job to start. This will be used to identify the job if there is a need to delete it latter. :type weeks: str :param date: Set the time to call sendCommand :type date: datetime :param args: the arguments to call sendCommand with :type weeks: tuple :param date: the kwwargs to call sendCommand with :type date: dictionary ''' name = args[0] self.logger.debug( 'add date({}) at {}'.format( name, date ) ) token = self.scheduler.add_date_job( self.sendCommand, date=date, args=args, kwargs=kwargs ) self.jobs[name].append( token ) def add_one_shot( self, delta, args=None, kwargs=None ): ''' Schedule sendCommand to be called after some interval. (ie. in 5 seconds or one hour). For more information on timeDelta see: .. seealso:: http://docs.python.org/2/library/datetime.html#timedelta-objects :param name: delta the time until sendCommand is called :type weeks: timedelta :param date: Set the time to call sendCommand :type date: datetime :param args: the arguments to call sendCommand with :type weeks: tuple :param date: the kwwargs to call sendCommand with :type date: dictionary ''' name = args[0] now = GetDateTime() dt = now.datetime() dt = dt + delta token = self.scheduler.add_date_job( self.sendCommand, date=dt, name=name, args=args, kwargs=kwargs ) self.jobs[name].append( token ) def deleteJob( self, name ): ''' Delete a specified job :param name: the name of the job to delete. :type weeks: str ''' item = None if name in self.jobs: for number, item in enumerate( self.jobs[name] ): try: self.scheduler.unschedule_job( item ) except KeyError: pass self.logger.info( '{} "{}" removed from scheduler'.format( number, name ) ) self.jobs[name] = [] def shutdown( self, wait=True ): ''' shutdown the scheduler .. seealso: http://packages.python.org/APScheduler/#shutting-down-the-scheduler :param wait: determines whether to wait on threads to commplete. :type wait: boolean ''' if ( self.scheduler != None ): self.scheduler.shutdown( wait=wait ) self.scheduler = None def print_jobs( self ): ''' print tye currently scheduled jobs .. seealso: http://packages.python.org/APScheduler/#getting-a-list-of-scheduled-jobs ''' self.scheduler.print_jobs() def sendCommand( self, name, device, port, listeners=[], scheduler_id=str( uuid.uuid4() ) ): """ send command will send the cammand to the HouseMonitor system :param device: the device name. :type device: str :param port: the port name. :type days: str :param listeners: the listeners that this command will be routed to. :type listeners: list of strings that contains the topic name of the listeners. Most can be found in Constants.TopicNames """ try: data = { Constants.EnvelopeContents.VALUE: 1, Constants.EnvelopeContents.DEVICE: device, Constants.EnvelopeContents.PORT: port, Constants.EnvelopeContents.SCHEDULER_ID: scheduler_id, Constants.EnvelopeContents.ARRIVAL_TIME: datetime.utcnow(), Constants.EnvelopeContents.STEPS: copy.copy( listeners ), Constants.EnvelopeContents.NAME: name, } de = DataEnvelope( Constants.EnvelopeTypes.STATUS, **data ) self.logger.debug( 'name: {} listeners: {} scheduler_id: {}'. format( name, listeners, data[Constants.EnvelopeContents.STEPS] ) ) self.__input_queue.transmit( de, self.__input_queue.LOW_PRIORITY ) except Exception as ex: self.logger.exception( "Exception in SendCommand: {}".format( ex ) )
class TestJobExecution(object): def setup(self): self.scheduler = Scheduler(threadpool=FakeThreadPool()) self.scheduler.add_jobstore(RAMJobStore(), 'default') # Make the scheduler think it's running self.scheduler._thread = FakeThread() self.logstream = StringIO() self.loghandler = StreamHandler(self.logstream) self.loghandler.setLevel(ERROR) scheduler.logger.addHandler(self.loghandler) def teardown(self): scheduler.logger.removeHandler(self.loghandler) if scheduler.datetime == FakeDateTime: scheduler.datetime = datetime FakeDateTime._now = original_now @raises(TypeError) def test_noncallable(self): date = datetime.now() + timedelta(days=1) self.scheduler.add_date_job('wontwork', date) def test_job_name(self): def my_job(): pass job = self.scheduler.add_interval_job(my_job, start_date=datetime(2010, 5, 19)) eq_( repr(job), '<Job (name=my_job, ' 'trigger=<IntervalTrigger (interval=datetime.timedelta(0, 1), ' 'start_date=datetime.datetime(2010, 5, 19, 0, 0))>)>') def test_schedule_object(self): # Tests that any callable object is accepted (and not just functions) class A: def __init__(self): self.val = 0 def __call__(self): self.val += 1 a = A() job = self.scheduler.add_interval_job(a, seconds=1) self.scheduler._process_jobs(job.next_run_time) self.scheduler._process_jobs(job.next_run_time) eq_(a.val, 2) def test_schedule_method(self): # Tests that bound methods can be scheduled (at least with RAMJobStore) class A: def __init__(self): self.val = 0 def method(self): self.val += 1 a = A() job = self.scheduler.add_interval_job(a.method, seconds=1) self.scheduler._process_jobs(job.next_run_time) self.scheduler._process_jobs(job.next_run_time) eq_(a.val, 2) def test_unschedule_job(self): def increment(): vals[0] += 1 vals = [0] job = self.scheduler.add_cron_job(increment) self.scheduler._process_jobs(job.next_run_time) eq_(vals[0], 1) self.scheduler.unschedule_job(job) self.scheduler._process_jobs(job.next_run_time) eq_(vals[0], 1) def test_unschedule_func(self): def increment(): vals[0] += 1 def increment2(): vals[0] += 1 vals = [0] job1 = self.scheduler.add_cron_job(increment) job2 = self.scheduler.add_cron_job(increment2) job3 = self.scheduler.add_cron_job(increment) eq_(self.scheduler.get_jobs(), [job1, job2, job3]) self.scheduler.unschedule_func(increment) eq_(self.scheduler.get_jobs(), [job2]) @raises(KeyError) def test_unschedule_func_notfound(self): self.scheduler.unschedule_func(copy) def test_job_finished(self): def increment(): vals[0] += 1 vals = [0] job = self.scheduler.add_interval_job(increment, max_runs=1) self.scheduler._process_jobs(job.next_run_time) eq_(vals, [1]) assert job not in self.scheduler.get_jobs() def test_job_exception(self): def failure(): raise DummyException job = self.scheduler.add_date_job(failure, datetime(9999, 9, 9)) self.scheduler._process_jobs(job.next_run_time) assert 'DummyException' in self.logstream.getvalue() def test_misfire_grace_time(self): self.scheduler.misfire_grace_time = 3 job = self.scheduler.add_interval_job(lambda: None, seconds=1) eq_(job.misfire_grace_time, 3) job = self.scheduler.add_interval_job(lambda: None, seconds=1, misfire_grace_time=2) eq_(job.misfire_grace_time, 2) def test_coalesce_on(self): # Makes sure that the job is only executed once when it is scheduled # to be executed twice in a row def increment(): vals[0] += 1 vals = [0] events = [] scheduler.datetime = FakeDateTime self.scheduler.add_listener(events.append, EVENT_JOB_EXECUTED | EVENT_JOB_MISSED) job = self.scheduler.add_interval_job(increment, seconds=1, start_date=FakeDateTime.now(), coalesce=True, misfire_grace_time=2) # Turn the clock 14 seconds forward FakeDateTime._now += timedelta(seconds=2) self.scheduler._process_jobs(FakeDateTime.now()) eq_(job.runs, 1) eq_(len(events), 1) eq_(events[0].code, EVENT_JOB_EXECUTED) eq_(vals, [1]) def test_coalesce_off(self): # Makes sure that every scheduled run for the job is executed even # when they are in the past (but still within misfire_grace_time) def increment(): vals[0] += 1 vals = [0] events = [] scheduler.datetime = FakeDateTime self.scheduler.add_listener(events.append, EVENT_JOB_EXECUTED | EVENT_JOB_MISSED) job = self.scheduler.add_interval_job(increment, seconds=1, start_date=FakeDateTime.now(), coalesce=False, misfire_grace_time=2) # Turn the clock 2 seconds forward FakeDateTime._now += timedelta(seconds=2) self.scheduler._process_jobs(FakeDateTime.now()) eq_(job.runs, 3) eq_(len(events), 3) eq_(events[0].code, EVENT_JOB_EXECUTED) eq_(events[1].code, EVENT_JOB_EXECUTED) eq_(events[2].code, EVENT_JOB_EXECUTED) eq_(vals, [3]) def test_interval(self): def increment(amount): vals[0] += amount vals[1] += 1 vals = [0, 0] job = self.scheduler.add_interval_job(increment, seconds=1, args=[2]) self.scheduler._process_jobs(job.next_run_time) self.scheduler._process_jobs(job.next_run_time) eq_(vals, [4, 2]) def test_interval_schedule(self): @self.scheduler.interval_schedule(seconds=1) def increment(): vals[0] += 1 vals = [0] start = increment.job.next_run_time self.scheduler._process_jobs(start) self.scheduler._process_jobs(start + timedelta(seconds=1)) eq_(vals, [2]) def test_cron(self): def increment(amount): vals[0] += amount vals[1] += 1 vals = [0, 0] job = self.scheduler.add_cron_job(increment, args=[3]) start = job.next_run_time self.scheduler._process_jobs(start) eq_(vals, [3, 1]) self.scheduler._process_jobs(start + timedelta(seconds=1)) eq_(vals, [6, 2]) self.scheduler._process_jobs(start + timedelta(seconds=2)) eq_(vals, [9, 3]) def test_cron_schedule_1(self): @self.scheduler.cron_schedule() def increment(): vals[0] += 1 vals = [0] start = increment.job.next_run_time self.scheduler._process_jobs(start) self.scheduler._process_jobs(start + timedelta(seconds=1)) eq_(vals[0], 2) def test_cron_schedule_2(self): @self.scheduler.cron_schedule(minute='*') def increment(): vals[0] += 1 vals = [0] start = increment.job.next_run_time next_run = start + timedelta(seconds=60) eq_(increment.job.get_run_times(next_run), [start, next_run]) self.scheduler._process_jobs(start) self.scheduler._process_jobs(next_run) eq_(vals[0], 2) def test_date(self): def append_val(value): vals.append(value) vals = [] date = datetime.now() + timedelta(seconds=1) self.scheduler.add_date_job(append_val, date, kwargs={'value': 'test'}) self.scheduler._process_jobs(date) eq_(vals, ['test']) def test_print_jobs(self): out = StringIO() self.scheduler.print_jobs(out) expected = 'Jobstore default:%s'\ ' No scheduled jobs%s' % (os.linesep, os.linesep) eq_(out.getvalue(), expected) self.scheduler.add_date_job(copy, datetime(2200, 5, 19)) out = StringIO() self.scheduler.print_jobs(out) expected = 'Jobstore default:%s '\ 'copy (trigger: date[2200-05-19 00:00:00], '\ 'next run at: 2200-05-19 00:00:00)%s' % (os.linesep, os.linesep) eq_(out.getvalue(), expected) def test_jobstore(self): self.scheduler.add_jobstore(RAMJobStore(), 'dummy') job = self.scheduler.add_date_job(lambda: None, datetime(2200, 7, 24), jobstore='dummy') eq_(self.scheduler.get_jobs(), [job]) self.scheduler.remove_jobstore('dummy') eq_(self.scheduler.get_jobs(), []) @raises(KeyError) def test_remove_nonexistent_jobstore(self): self.scheduler.remove_jobstore('dummy2') def test_job_next_run_time(self): # Tests against bug #5 def increment(): vars[0] += 1 vars = [0] scheduler.datetime = FakeDateTime job = self.scheduler.add_interval_job(increment, seconds=1, misfire_grace_time=3, start_date=FakeDateTime.now()) start = job.next_run_time self.scheduler._process_jobs(start) eq_(vars, [1]) self.scheduler._process_jobs(start) eq_(vars, [1]) self.scheduler._process_jobs(start + timedelta(seconds=1)) eq_(vars, [2])
class TestJobExecution(object): def setup(self): self.scheduler = Scheduler(threadpool=FakeThreadPool()) self.scheduler.add_jobstore(RAMJobStore(), "default") # Make the scheduler think it's running self.scheduler._thread = FakeThread() self.logstream = StringIO() self.loghandler = StreamHandler(self.logstream) self.loghandler.setLevel(ERROR) scheduler.logger.addHandler(self.loghandler) def teardown(self): scheduler.logger.removeHandler(self.loghandler) if scheduler.datetime == FakeDateTime: scheduler.datetime = datetime FakeDateTime._now = original_now def test_job_name(self): def my_job(): pass job = self.scheduler.add_interval_job(my_job, start_date=datetime(2010, 5, 19)) eq_( repr(job), "<Job (name=my_job, trigger=<IntervalTrigger (interval=datetime.timedelta(0, 1), " "start_date=datetime.datetime(2010, 5, 19, 0, 0))>)>", ) def test_schedule_object(self): # Tests that any callable object is accepted (and not just functions) class A: def __init__(self): self.val = 0 def __call__(self): self.val += 1 a = A() job = self.scheduler.add_interval_job(a, seconds=1) self.scheduler._process_jobs(job.next_run_time) self.scheduler._process_jobs(job.next_run_time) eq_(a.val, 2) def test_schedule_method(self): # Tests that bound methods can be scheduled (at least with RAMJobStore) class A: def __init__(self): self.val = 0 def method(self): self.val += 1 a = A() job = self.scheduler.add_interval_job(a.method, seconds=1) self.scheduler._process_jobs(job.next_run_time) self.scheduler._process_jobs(job.next_run_time) eq_(a.val, 2) def test_unschedule_job(self): def increment(): vals[0] += 1 vals = [0] job = self.scheduler.add_cron_job(increment) self.scheduler._process_jobs(job.next_run_time) eq_(vals[0], 1) self.scheduler.unschedule_job(job) self.scheduler._process_jobs(job.next_run_time) eq_(vals[0], 1) def test_unschedule_func(self): def increment(): vals[0] += 1 def increment2(): vals[0] += 1 vals = [0] job1 = self.scheduler.add_cron_job(increment) job2 = self.scheduler.add_cron_job(increment2) job3 = self.scheduler.add_cron_job(increment) eq_(self.scheduler.get_jobs(), [job1, job2, job3]) self.scheduler.unschedule_func(increment) eq_(self.scheduler.get_jobs(), [job2]) @raises(KeyError) def test_unschedule_func_notfound(self): self.scheduler.unschedule_func(copy) def test_job_finished(self): def increment(): vals[0] += 1 vals = [0] job = self.scheduler.add_interval_job(increment, max_runs=1) self.scheduler._process_jobs(job.next_run_time) eq_(vals, [1]) assert job not in self.scheduler.get_jobs() def test_job_exception(self): def failure(): raise DummyException job = self.scheduler.add_date_job(failure, datetime(9999, 9, 9)) self.scheduler._process_jobs(job.next_run_time) assert "DummyException" in self.logstream.getvalue() def test_misfire_grace_time(self): self.scheduler.misfire_grace_time = 3 job = self.scheduler.add_interval_job(lambda: None, seconds=1) eq_(job.misfire_grace_time, 3) job = self.scheduler.add_interval_job(lambda: None, seconds=1, misfire_grace_time=2) eq_(job.misfire_grace_time, 2) def test_coalesce_on(self): # Makes sure that the job is only executed once when it is scheduled # to be executed twice in a row def increment(): vals[0] += 1 vals = [0] events = [] scheduler.datetime = FakeDateTime self.scheduler.add_listener(events.append, EVENT_JOB_EXECUTED | EVENT_JOB_MISSED) job = self.scheduler.add_interval_job( increment, seconds=1, start_date=FakeDateTime.now(), coalesce=True, misfire_grace_time=2 ) # Turn the clock 14 seconds forward FakeDateTime._now += timedelta(seconds=2) self.scheduler._process_jobs(FakeDateTime.now()) eq_(job.runs, 1) eq_(len(events), 1) eq_(events[0].code, EVENT_JOB_EXECUTED) eq_(vals, [1]) def test_coalesce_off(self): # Makes sure that every scheduled run for the job is executed even # when they are in the past (but still within misfire_grace_time) def increment(): vals[0] += 1 vals = [0] events = [] scheduler.datetime = FakeDateTime self.scheduler.add_listener(events.append, EVENT_JOB_EXECUTED | EVENT_JOB_MISSED) job = self.scheduler.add_interval_job( increment, seconds=1, start_date=FakeDateTime.now(), coalesce=False, misfire_grace_time=2 ) # Turn the clock 2 seconds forward FakeDateTime._now += timedelta(seconds=2) self.scheduler._process_jobs(FakeDateTime.now()) eq_(job.runs, 3) eq_(len(events), 3) eq_(events[0].code, EVENT_JOB_EXECUTED) eq_(events[1].code, EVENT_JOB_EXECUTED) eq_(events[2].code, EVENT_JOB_EXECUTED) eq_(vals, [3]) def test_interval(self): def increment(amount): vals[0] += amount vals[1] += 1 vals = [0, 0] job = self.scheduler.add_interval_job(increment, seconds=1, args=[2]) self.scheduler._process_jobs(job.next_run_time) self.scheduler._process_jobs(job.next_run_time) eq_(vals, [4, 2]) def test_interval_schedule(self): @self.scheduler.interval_schedule(seconds=1) def increment(): vals[0] += 1 vals = [0] start = increment.job.next_run_time self.scheduler._process_jobs(start) self.scheduler._process_jobs(start + timedelta(seconds=1)) eq_(vals, [2]) def test_cron(self): def increment(amount): vals[0] += amount vals[1] += 1 vals = [0, 0] job = self.scheduler.add_cron_job(increment, args=[3]) start = job.next_run_time self.scheduler._process_jobs(start) eq_(vals, [3, 1]) self.scheduler._process_jobs(start + timedelta(seconds=1)) eq_(vals, [6, 2]) self.scheduler._process_jobs(start + timedelta(seconds=2)) eq_(vals, [9, 3]) def test_cron_schedule_1(self): @self.scheduler.cron_schedule() def increment(): vals[0] += 1 vals = [0] start = increment.job.next_run_time self.scheduler._process_jobs(start) self.scheduler._process_jobs(start + timedelta(seconds=1)) eq_(vals[0], 2) def test_cron_schedule_2(self): @self.scheduler.cron_schedule(minute="*") def increment(): vals[0] += 1 vals = [0] start = increment.job.next_run_time next_run = start + timedelta(seconds=60) eq_(increment.job.get_run_times(next_run), [start, next_run]) self.scheduler._process_jobs(start) self.scheduler._process_jobs(next_run) eq_(vals[0], 2) def test_date(self): def append_val(value): vals.append(value) vals = [] date = datetime.now() + timedelta(seconds=1) self.scheduler.add_date_job(append_val, date, kwargs={"value": "test"}) self.scheduler._process_jobs(date) eq_(vals, ["test"]) def test_print_jobs(self): out = StringIO() self.scheduler.print_jobs(out) expected = "Jobstore default:%s" " No scheduled jobs%s" % (os.linesep, os.linesep) eq_(out.getvalue(), expected) self.scheduler.add_date_job(copy, datetime(2200, 5, 19)) out = StringIO() self.scheduler.print_jobs(out) expected = ( "Jobstore default:%s " "copy (trigger: date[2200-05-19 00:00:00], " "next run at: 2200-05-19 00:00:00)%s" % (os.linesep, os.linesep) ) eq_(out.getvalue(), expected) def test_jobstore(self): self.scheduler.add_jobstore(RAMJobStore(), "dummy") job = self.scheduler.add_date_job(lambda: None, datetime(2200, 7, 24), jobstore="dummy") eq_(self.scheduler.get_jobs(), [job]) self.scheduler.remove_jobstore("dummy") eq_(self.scheduler.get_jobs(), []) @raises(KeyError) def test_remove_nonexistent_jobstore(self): self.scheduler.remove_jobstore("dummy2") def test_job_next_run_time(self): # Tests against bug #5 def increment(): vars[0] += 1 vars = [0] scheduler.datetime = FakeDateTime job = self.scheduler.add_interval_job(increment, seconds=1, misfire_grace_time=3, start_date=FakeDateTime.now()) start = job.next_run_time self.scheduler._process_jobs(start) eq_(vars, [1]) self.scheduler._process_jobs(start) eq_(vars, [1]) self.scheduler._process_jobs(start + timedelta(seconds=1)) eq_(vars, [2])
sched = Scheduler() signal.signal(signal.SIGINT, shutdown_handler) signal.signal(signal.SIGTERM, shutdown_handler) def event_handler(event): if event.exception: logger.error("SCHEDULER FAIL:\n%s\n%s\n%s" % (event.job, event.exception, traceback.format_exc())) else: logger.info("SUCCESS: %s" % event.job) sched.add_listener( event_handler, events.EVENT_JOB_EXECUTED | events.EVENT_JOB_ERROR | events.EVENT_JOB_MISSED) # ---------------------------------------------------------------------------- # Tasks #sched.add_cron_job(send_digest, hour=11) # ---------------------------------------------------------------------------- if __name__ == '__main__': sched.start() sched.print_jobs() while True: time.sleep(10) db.remove()
# Start the scheduler sched = Scheduler() sched.add_jobstore( SQLAlchemyJobStore(url=JOBS_DATABASE, tablename='apscheduler_jobs'), 'default') sched.start() def print_reservation_id(reservation_id): print "====> Reservation id is " + str(reservation_id) if __name__ == '__main__': print "====> Printing jobs..." print sched.print_jobs() now = datetime.datetime.now() start_time = now + datetime.timedelta(seconds=3) later = now + datetime.timedelta(seconds=10) print "====> now is " + str(now) print "====> start_time is " + str(start_time) print "====> later is " + str(later) reservation_id = 1 job_name = "print_reservation_id_" + str(reservation_id) print "====> adding start_time job"