Thread terminate

Chris Kaynor ckaynor at zindagigames.com
Wed Aug 27 15:26:48 EDT 2014


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.


>
> 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. 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")
>
>         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.

    ....
>     def terminate(self, msg):
>         self.error = True
>         self.errormsg = msg
>         syslog.syslog(syslog.LOG_DEBUG, msg)
>         raise Exception(msg)
>
>
> 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.

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.

    except:
>         mt.join()


> 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.


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.

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.


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.

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).
This can reduce the overhead associated with threads and provide better
performance - both locally and, with database connections, on the server.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-list/attachments/20140827/c8298a99/attachment.html>


More information about the Python-list mailing list