On Thursday, June 27, 2019, 03:40:56 PM PDT, Yonatan Zunger <zunger@humu.com> wrote:

> One possible approach (at a very schematic level, not thinking about impl details yet) would be to have a function like Thread.raise(e: BaseException) which stuffs the exception into thread-local storage, which then gets checked at similar times to signals. (Probably not the exact same times since I'm sure there's plenty of code depending implicitly on that function being a noop outside the main thread) Basically, it would be having the Python interpreter doing the cooperative part of cross-thread interruption, so that it would look non-cooperative from the user side. You could even have a Thread.raiseWhen to do the equivalent of setting an alarm.

You could build a hacky version of this today in just a few lines, something like this:

class AbortableThread(threading.Thread):
    def __init__(self, *args, **kw):
        super().__init__(*args, **kw)
        self._e = None
    def _trace(self, frame, event, arg):
        if self._e:
            raise self._e()
        return self._trace
    def run(self, *args, **kw):
        sys.settrace(self._trace)
        super().run(*args, **kw)
    def throw(self, e):
        self._e = e

You wouldn't want to do this in practice, but for playing with the API to see if it feels right/usable, it should be fine.