diff --git a/README.md b/README.md index b3aac61..81acc8e 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,7 @@ Inspired by this blog [`here`](https://www.g-loaded.eu/2016/11/24/how-to-termina pip install timeloop ``` -## writing a job looks like this - +## Writing jobs ```python import time @@ -32,8 +31,28 @@ def sample_job_every_5s(): @tl.job(interval=timedelta(seconds=10)) def sample_job_every_10s(): print "10s job current time : {}".format(time.ctime()) +``` +## Start time loop in separate thread +By default timeloop starts in a separate thread. + +Please do not forget to call ```tl.stop``` before exiting the program, Or else the jobs wont shut down gracefully. + +```python tl.start() + +while True: + try: + time.sleep(1) + except KeyboardInterrupt: + tl.stop() + break +``` + +## Start time loop in main thread +Doing this will automatically shut down the jobs gracefully when the program is killed, so no need to call ```tl.stop``` +```python +tl.start(block=True) ``` ## Author diff --git a/setup.py b/setup.py index ebf45d8..e3cc372 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ with open("README.md", "r") as fh: setup( name='timeloop', - version='1.0', + version='1.0.1', packages=['timeloop'], license = 'MIT', description = 'An elegant way to run period tasks.', diff --git a/timeloop/app.py b/timeloop/app.py index d4afa72..65b2a27 100644 --- a/timeloop/app.py +++ b/timeloop/app.py @@ -16,33 +16,46 @@ class Timeloop(): logger.setLevel(logging.INFO) self.logger = logger - def _add_task(self, func, interval, *args, **kwargs): + def _add_job(self, func, interval, *args, **kwargs): j = Job(interval, func, *args, **kwargs) self.jobs.append(j) + def _block_main_thread(self): + signal.signal(signal.SIGTERM, service_shutdown) + signal.signal(signal.SIGINT, service_shutdown) + + while True: + try: + time.sleep(1) + except ServiceExit: + self.stop() + break + + def _start_jobs(self, block): + for j in self.jobs: + j.daemon = not block + j.start() + self.logger.info("Registered job {}".format(j.execute)) + + def _stop_jobs(self): + for j in self.jobs: + self.logger.info("Stopping job {}".format(j.execute)) + j.stop() + def job(self, interval): def decorator(f): - self._add_task(f, interval) + self._add_job(f, interval) return f return decorator - def start(self): - try: - signal.signal(signal.SIGTERM, service_shutdown) - signal.signal(signal.SIGINT, service_shutdown) + def stop(self): + self._stop_jobs() + self.logger.info("Timeloop exited.") - self.logger.info("Starting Timeloop..") - for j in self.jobs: - self.logger.info("Registered task {}".format(j.execute)) - j.start() - self.logger.info("Timeloop now started. Tasks will run based on the interval set") + def start(self, block=False): + self.logger.info("Starting Timeloop..") + self._start_jobs(block=block) - # block main thead - while True: - time.sleep(1) - - except ServiceExit: - for j in self.jobs: - self.logger.info("Stopping task {}".format(j.execute)) - j.stop() - self.logger.info("Timeloop exited.") + self.logger.info("Timeloop now started. Jobs will run based on the interval set") + if block: + self._block_main_thread() diff --git a/timeloop/job.py b/timeloop/job.py index 3e6761d..df97d2f 100644 --- a/timeloop/job.py +++ b/timeloop/job.py @@ -17,10 +17,3 @@ class Job(Thread): def run(self): while not self.stopped.wait(self.interval.total_seconds()): self.execute(*self.args, **self.kwargs) - -def sample_func(arg1, arg2, arg3): - print "returning {} {} {}".format(arg1, arg2, arg3) - -if __name__ == "__main__": - j = Job(timedelta(seconds=5), sample_func, **{"arg1": "sankalp", "arg2": "jonna", "arg3": "newsomething"}) - j.start()