Thread terminate

Ervin Hegedüs airween at gmail.com
Thu Aug 28 04:52:11 EDT 2014


Hi Chris,

thanks for the reply,

On Wed, Aug 27, 2014 at 12:26:48PM -0700, Chris Kaynor wrote:
> On Wed, Aug 27, 2014 at 11:55 AM, Ervin Hegedüs <airween at gmail.com> wrote:
> 
> > what's the correct way to terminate a thread by itself?
> >
> 
> To terminate the thread, the run function must exit. This can be either
> from an exception or a return statement.

you mean:

    def run(self):
        do_domething()
        return True

is enough?

> > I mean:
> >
> > class MyThread(threading.Thread):
> >     def __init__(self, queueitem):
> >         threading.Thread.__init__(self)
> >         ...
> >
> >     def run(self):
> >         """pseudo code below"""
> >
> >         try:
> >            self.connect_to_database()
> >         except:
> >
> 
> First off, especially if you are going to raise an exception anyways, I
> would recommend not silencing the orignal error - it will make debugging
> harder. 

That's right - I just copied the relevant code.

> This is especially true with a bare "except:" statement - at least
> capture only some exceptions. Using a logger to handle the exception or use
> your except, log the error, than reraise with a bare "raise" statement
> would generally be preferable.
> 
>            self.terminate("Error when connect to db")

thanks for the idea,

> >
> >         try:
> >            self.create_db_table()
> >         except:
> >            self.terminate("Error when create table")
> >
> 
> You probably want to make sure to disconnect from the database in here.
> Possibly via a "with" statement or a "try...finally" over the entire block,
> depending on your database API.

right,
 
> > in main():
> >
> > for q in range(0, 10):
> >     mt = MyThread()
> >     try:
> >         mt.run()
> >
> 
> This is not actually starting a thread, but is running it in-line, just
> like a normal function. You probably want "mt.start()" instead, which will
> cause "mt.run" to execute in another thread.
yes, I know that, and I've used mt.start() before the mt.run() -
I just missed out to paste that part of code - sorry.
 
> If you use mt.start() to actually start a thread, the only time it will
> fail is if the thread fails to start (such as too many running threads, or
> other out-of-resource errors). The exceptions raised inside the thread will
> not propagate outside the start call, and thus the mt.join() call inside
> the except statement will have no effect - no thread is running.

yes, I thought that, this triggered my question :)
 
> > but it doesn't works - the exception showed on stdout only, and
> > the thread stops of course, but I would like to handle the
> > exceptions. If I call the join() inside from thread object, then
> > an exception raised, cause the thread object of Threading module
> > doesn't allows that...
> >
> 
> Not being able to call join from the thread you are joining with is
> probably a good thing - doing so would result in a dead lock: the thread is
> waiting for the thread to exit.

ah, well, I understand it now...
 
> 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 the case of handling the problems in the main thread, your main thread
> code would look something like:
> 
> # Start all of the threads up-front.
> 
> threads = []
> for q in range(0, 10):
>     mt = MyThread()
>     mt.start() # NOT mt.run() - that does not do any threading!
>     threads.append(mt)
> 
> # Now wait for them to complete.
> 
> for thread in threads:
>     thread.join()
>     # Check for the status of thread here. Possibly on the thread object,
> which can be mutated in MyThread.run by assigning to members of self.
> 

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.

The process will be forked, and will runs in background when I'll
finished that, so it could be good to controll all messages.

> In the sample code you are doing, I am not even sure if I would use threads
> due to the added complexities associated with them. In the case of merely
> connecting to a database and creating a few tables, you can probably get by
> with doing them in a single thread: open a single connection, creating the
> tables as a sequence of operations, commit operations, and close connection.

at this time there is only one thread, as you wrote. I just try
to prepare it to higher load, when one thread will not enough...
 
> If you do in fact need threads, you may also be better off using a thread
> pool (see concurrent.futures, available in Python 3.2 and higher only).

I've only Python 2.5 at my developing system, the production has
Python 2.7, and it has 3.2 too, but I don't know the components
how compatibles with Python 3.2 (eg. MySQLdb). Anyway, I feel
better with Python 2.(6|7) :)


> This can reduce the overhead associated with threads and provide better
> performance - both locally and, with database connections, on the server.

If I will switch to Python 3 finally, I'll check it out :)


Thanks again,


a.




More information about the Python-list mailing list