Catch a thread's exception in the caller thread?
The problem is that thread_obj.start()
returns immediately. The child thread that you spawned executes in its own context, with its own stack. Any exception that occurs there is in the context of the child thread, and it is in its own stack. One way I can think of right now to communicate this information to the parent thread is by using some sort of message passing, so you might look into that.
Try this on for size:
import sys
import threading
import queue
class ExcThread(threading.Thread):
def __init__(self, bucket):
threading.Thread.__init__(self)
self.bucket = bucket
def run(self):
try:
raise Exception('An error occured here.')
except Exception:
self.bucket.put(sys.exc_info())
def main():
bucket = queue.Queue()
thread_obj = ExcThread(bucket)
thread_obj.start()
while True:
try:
exc = bucket.get(block=False)
except queue.Empty:
pass
else:
exc_type, exc_obj, exc_trace = exc
# deal with the exception
print exc_type, exc_obj
print exc_trace
thread_obj.join(0.1)
if thread_obj.isAlive():
continue
else:
break
if __name__ == '__main__':
main()
How to catch an exception which occured in a thread?
The exact answer to my problem was given in an answer to another question (I marked mine as duplicate, but it is really that particular answer which is perfect in my context).
The code in my question modified to account for the solution:
import concurrent.futures
class Checks:
@staticmethod
def isok():
print("OK")
@staticmethod
def isko():
raise Exception("KO")
# db will keep a map of method namles in Check with the actual (executable) method
db = {}
with concurrent.futures.ThreadPoolExecutor(max_workers=1) as executor:
for check in [k for k in dir(Checks) if not k.startswith('_')]:
db[check] = executor.submit(getattr(Checks, check))
for future in concurrent.futures.as_completed([db[k] for k in db.keys()]):
if future.exception():
print(f"{str(future.exception())} was raised (I do not know where, somewhere)")
else:
print("success (again, I do not know where, exactly)")
# all the threads are finished at that point
print("all threads are done")
I do not know how to get the name of the future which raised the exception (I will ask a new question about that)
How to catch an Exception from a thread
Use a Thread.UncaughtExceptionHandler
.
Thread.UncaughtExceptionHandler h = new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread th, Throwable ex) {
System.out.println("Uncaught exception: " + ex);
}
};
Thread t = new Thread() {
@Override
public void run() {
System.out.println("Sleeping ...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("Interrupted.");
}
System.out.println("Throwing exception ...");
throw new RuntimeException();
}
};
t.setUncaughtExceptionHandler(h);
t.start();
How to catch exceptions that happened in a python threading.Thread execution?
Try this one.
When you catch it in thread's caller, you can easily email it like you used to do.
Catch a thread's exception in the caller thread in Python
can't catch exception in main thread when other thread active and has try-catch
It's not so much that the exception isn't caught as it is that destroying a joinable thread terminates the process.
So your program terminates before the exception handler can be executed.
If you declare the thread outside the try-catch block, the exception will be caught.
Remember that you also need to join the thread if the exception was thrown.
Catch exception after thread is done
You can use Task
with an STA thread (which I assume is what you want).
To do so, you can write some helper methods to start a task on a thread that has been set to STA:
public static class STATask
{
/// <summary>
/// Similar to Task.Run(), except this creates a task that runs on a thread
/// in an STA apartment rather than Task's MTA apartment.
/// </summary>
/// <typeparam name="TResult">The return type of the task.</typeparam>
/// <param name="function">The work to execute asynchronously.</param>
/// <returns>A task object that represents the work queued to execute on an STA thread.</returns>
[NotNull] public static Task<TResult> Run<TResult>([NotNull] Func<TResult> function)
{
var tcs = new TaskCompletionSource<TResult>();
var thread = new Thread(() =>
{
try
{
tcs.SetResult(function());
}
catch (Exception e)
{
tcs.SetException(e);
}
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
return tcs.Task;
}
/// <summary>
/// Similar to Task.Run(), except this creates a task that runs on a thread
/// in an STA apartment rather than Task's MTA apartment.
/// </summary>
/// <param name="action">The work to execute asynchronously.</param>
/// <returns>A task object that represents the work queued to execute on an STA thread.</returns>
[NotNull] public static Task Run([NotNull] Action action)
{
var tcs = new TaskCompletionSource<object>(); // Return type is irrelevant for an Action.
var thread = new Thread(() =>
{
try
{
action();
tcs.SetResult(null); // Irrelevant.
}
catch (Exception e)
{
tcs.SetException(e);
}
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
return tcs.Task;
}
}
Once you have that, you can easily create an STA task and then use .ContinueWith()
to handle exceptions thrown in the task, or use await
to catch the exceptions.
(Note: [NotNull]
is from Resharper annotations - remove them if you're not using Resharper.)
Related Topics
How to Send a Head Http Request in Python 2
How to Get Monitor Resolution in Python
Method Resolution Order (Mro) in New-Style Classes
Getting the Index of the Returned Max or Min Item Using Max()/Min() on a List
What Soap Client Libraries Exist for Python, and Where Is the Documentation for Them
Importerror: Dll Load Failed: the Specified Module Could Not Be Found
I'm Getting Key Error in Python
Best Way to Find the Intersection of Multiple Sets
Python 3 Importerror: No Module Named 'Configparser'
How to Add a Constant Column in a Spark Dataframe
Differencebetween Nan and None
Unicodedecodeerror: 'Utf8' Codec Can't Decode Byte 0Xa5 in Position 0: Invalid Start Byte
Keep Only Date Part When Using Pandas.To_Datetime
What Is the Most Efficient Way of Finding All the Factors of a Number in Python