Thread terminate

Chris Kaynor ckaynor at zindagigames.com
Thu Aug 28 15:34:18 EDT 2014


On Thu, Aug 28, 2014 at 11:39 AM, Ervin Hegedüs <airween at gmail.com> wrote:

> Hi Chris,
>
> thanks for you answer,
>
> On Thu, Aug 28, 2014 at 09:23:24AM -0700, Chris Kaynor wrote:
> > On Thu, Aug 28, 2014 at 1:52 AM, Ervin Hegedüs <airween at gmail.com>
> wrote:
> > >
> > >  > In your case, you may want to just handle the exceptions inside the
> > > > thread's run() function directly. If that is not possible and you
> really
> > > > need to handle them inside the main thread, you would need to store
> off
> > > the
> > > > error data in a variable (either passed into the thread as the
> "args" or
> > > > "kwargs" arguments to the MyThread() call, or global or class
> variables)
> > > > then use mt.join() to wait for the thread(s) to exit.
> > >
> > > no, I don't need to handle it outside of thread - the point is
> > > when the exception raised in a running thread, then the exception
> > > be logged (that's no problem), and thread be stopped state, so
> > > the caller function is able to call the join() that thread.
> >
> >
> > In this case, all that needs to happen is for the thread's run function
> to
> > either throw an exception (as happens in the error case in your sample
> > code) or return.
>
> now the code looks like this:
>
>   def run(self):
>     try:
>       connect_to_db()
>     except:
>       self._exit(-1, "Connection error", sys.exc_info()[1])
>       return True
>
>     try:
>       do_another_thing()
>     except:
>       self._exit(-2, "Another error", sys.exc_info()[1])
>       return True
>
>
You could also do this this way:

def run(self):
    try:
        try:
          connect_to_db()
        except:
          self._exit(-1, "Connection error", sys.exc_info()[1])
          raise # could do something similar inside self._exit instead.

        try:
          do_another_thing()
        except:
          self._exit(-2, "Another error", sys.exc_info()[1])
          raise # could do something similar inside self._exit instead.
    except:
        return True

I'm not sure that is any clearer.

depending on what you are doing with the first two arguments to self._exit,
the following might also work:

def run(self):
    try:
        connect_to_db()
        do_another_thing()
    except:
        self._exit(*sys.exc_info())
        return True

Of course, this has the issue that you do not get your extra information,
however, from my experience, typically the error type, message, and
traceback are sufficient, and rarely have I needed to provide additional
details.


> so, the thread's _exit() functions set many things, logs to
> exception error, but not terminate the thread. As you can see,
> all except line of try block contains a return - that's what I
> wanted to avoid.
>
> > The threading module will cause it to print any exception that occurs by
> > default.
>
> yes, I saw that :),
>
> > > yes, the pseudo structure of my code is same as your here. But
> > > the now the problem is when an exception raised, that showed at
> > > stdout too, not just the log.
> > >
> >
> > If what you want is to make sure the error is not printed to stderr,
> you'll
> > just need to make sure the thread's run function does not exit with an
> > exception. The simpliest way to do that would be to wrap the entire
> > thread's run function in a try...catch statement, like so:
>
> """I've re-indented your code below:"""
>
> > class Thread(threading.Thread)
> >
> >   def run(self):
> >     try:
> >       # Do your code here.
> >       # You can also have more specific error-handling inside here if
> needed.
> >     except Exception as err:
> >       # Log your error here - you will be silencing it and therefore
> unable to
> >       # see it in the TTY!
>
> Now I don't see the key different between your code, and my
> example - looks like there are same. But when I tried to throw an
> exception, that showed in TTY. Nevermind, now it works, only the
> necessary "return" keyword would be good to leave.
>

Effectively, your formatting is the same as what I was suggesting - I was
merely adding that you could wrap the entire block inside of a single
try..except rather than having multiple ones. That does have some drawbacks
(as mentioned above).

One solution I did not mention before, but is plausible, is to
monkey-patch/override the threading module to change the behavior
of _bootstrap_inner or _bootstrap to behave differently. As these are on
the Thread class, you could override them in your subclass or a base
subclass (depending on the number of Thread subclasses you have) that
behaves differently. Perhaps by making it call sys.excepthook. At one
point, we discussed doing something similar at work as we normally print
exceptions to custom streams that provide color formatting to make the
exceptions easier to find and read (exception message printed in red,
traceback in a dark red), as well as log.

Chris
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-list/attachments/20140828/25ccd592/attachment.html>


More information about the Python-list mailing list