Hi I have multiple functions running with thread. I am wondering how do you handle error in running multiple threads where it does not affect the other threads that are running. When a function breaks, the other functions stops too. Do I use a try except for every schedule? Or is there a better way?
Current structure is like this.
#--------------------------------------------------------------------------run_threaded function
def run_threaded(job_func):
job_thread = threading.Thread(target=job_func)
job_thread.start()
#------------------------------------------------------------------------scheduler function
#scheduler
print('scheduler is starting')
schedule.every().day.at('06:30').do(run_threaded,lambda:functionA())
schedule.every().day.at('06:30').do(run_threaded,lambda:functionB())
schedule.every().day.at('06:30').do(run_threaded,lambda:functionC())
schedule.every().day.at('06:30').do(run_threaded,lambda:functionD())
schedule.every().day.at('06:30').do(run_threaded,lambda:fucntionE())
schedule.every().day.at('22:00').do(lambda:email())
schedule.every().day.at('22:15').do(lambda:writeFile())
while True:
schedule.run_pending()
sleep(1)
CodePudding user response:
I want to start by stating that [Python.Docs]: threading - Thread-based parallelism does not actually do multithreading (on multiple CPUs), but it's more like a (lame) workaround (gainarie), because of GIL.
If you really want parallel execution, use [Python.Docs]: multiprocessing - Process-based parallelism.
But even if the above wasn't true, you actually do not have multithreading in your code. According to [ReadTheDocs.Schedule]: Schedule (if this is the module you are using), the methods (like do) expect a function as a parameter (same as threading.Thread initializer), but you're passing a function call (the parentheses () at the end).
So, you have sequential runs of the functions you're passing, and when the 1st one raises an exception, the whole program stops.
Taking the below line as an example:
schedule.every().day.at('06:30').do(run_threaded, lambda: functionA())
In [ReadTheDocs.Schedule]: Parallel execution (which was probably one of the sources of inspiration) the (target) function isn't called, so the above line should be:
schedule.every().day.at('06:30').do(run_threaded, lambda: functionA) # functionA isn't called (no parentheses at the end) but it's rather passed as an argument
Not sure what's lambda purpose, things would look much simpler without it:
schedule.every().day.at('06:30').do(run_threaded, functionA)
Apply the above steps to all the calls, and I think you'd be fine (functions runs that raise exceptions won't affect the ones that don't - at least that's the behavior in threading), in spite of the following (in the Schedule documentation URL):
When not to use Schedule
...
- Concurrent execution (multiple threads)