Search code examples
pythonschedule

python schedule - jobs from python list


I'd like to use python schedule library to schedule a large amount of jobs.
All jobs perform the same operations but on a different input.
The inputs are stored in a python list.

The idea is to put each input from the list into a shared queue and then process each one of them in sequence.

Here is an example and my attempt:

import queue
import time
import threading
import schedule

def job(name):
    print(name)


def worker_main():
    while 1:
        (job_func,job_msg) = jobqueue.get()
        job_func(job_msg)
        jobqueue.task_done()


name = ['jane', 'alice', 'mary']
jobqueue = queue.Queue()

schedule.every(2).seconds.do(jobqueue.put, (job, name))

worker_thread = threading.Thread(target=worker_main)
worker_thread.start()

while 1:
    schedule.run_pending()
    time.sleep(1)

Unfortunately, this approach run 1 job for all items in the list all together. Anyone has any suggestion? Thank you.


Solution

  • Printing every name in each 2 second interval:

    for n in name:
        schedule.every(2).seconds.do(jobqueue.put, (job, n))
    
    [Second 2]: jane
    [Second 2]: alice
    [Second 2]: mary
    [Second 4]: jane
    [Second 4]: alice
    [Second 4]: mary
    

    Printing a single name in each 2 second interval and looping through the list:

    from itertools import cycle
    name_iter = cycle(name)
    schedule.every(2).seconds.do(lambda: jobqueue.put((job, next(name_iter))))
    
    [Second 2]: jane
    [Second 4]: alice
    [Second 6]: mary
    [Second 8]: jane
    [Second 10]: alice
    [Second 12]: mary
    

    What if I do not want to use cycle but stop when the iterator has been consumed

    Looks like you can raise schedule.CancelJob https://schedule.readthedocs.io/en/stable/examples.html#run-a-job-once

    name_iter = iter(name)
    def queue_name():
        try:
            jobqueue.put((job, next(name_iter)))
        except StopIteration:
            return schedule.CancelJob
    
    schedule.every(1).seconds.do(queue_name)