Do thread die?

M

Maurice LING

Hi,

I just have a simple question about threads. My classes inherits from
threading.Thread class. I am calling threading.Thread.run() method to
spawn a few threads to parallel some parts of my program. No thread
re-use, pooling, joining ... just plainly spawn a thread, run a routine.

So, at the end of run(), what happens to the thread? Just die?

While I am on it, can threading.Thread.run() accept any parameters?

My current implementation may be ugly. I have a class

class myThread(threading.Thread):
def __init__(self, func):
self.func = func
threading.Thread.__init__(self)
def run(self):
print '%s function running' % self.func
self.func()

which is used in

class myClass: #using myThread
def __init__(self): pass
def aFunc(self): pass
def bFunc(self): pass
def runAll(self):
myThread(self.aFunc).start()
myThread(self.bFunc).start()

if __name__=='__main__': myClass().runAll()

Is this a good way?

Thanks and cheers
Maurice
 
S

Sybren Stuvel

Maurice LING enlightened us with:
So, at the end of run(), what happens to the thread? Just die?
Yep.

While I am on it, can threading.Thread.run() accept any parameters?

Nope. Pass them to the constructor and remember them.
class myThread(threading.Thread):
def __init__(self, func):
self.func = func
threading.Thread.__init__(self)
def run(self):
print '%s function running' % self.func
self.func()

You don't need to do this, since you can pass a callable object to the
Thread constructor. Read the first lines of
http://docs.python.org/lib/thread-objects.html again. That would
change your code to:

class myClass:
def __init__(self): pass
def aFunc(self): pass
def bFunc(self): pass

def runAll(self):
threading.Thread(self.aFunc).start()
threading.Thread(self.bFunc).start()

Sybren
 
B

Bryan Olson

Maurice said:
> Hi,
>
> I just have a simple question about threads. My classes inherits from
> threading.Thread class. I am calling threading.Thread.run() method to
> spawn a few threads to parallel some parts of my program. No thread
> re-use, pooling, joining ... just plainly spawn a thread, run a routine.
>
> So, at the end of run(), what happens to the thread? Just die?

Just die, mostly. It may do a bit of clean-up, setting its
affairs in order, arraning for burial/cremation/organ-donation
and such, to avoid leaving any problem for posterity.


Incidentally, the "threading" module, with its "Thread" class,
has one major advantage over the "thread" module: the "setDaemon"
method of class Thread.

> While I am on it, can threading.Thread.run() accept any parameters?

Not unless you override it; but you can pass parameters when
constructing the Thread, like this:

t = Thread(target=work_to_do, args=(67, 'Bill Johnston'), kwargs=some_dict)

t.start() will then execute the default Thread.run(), which
will execute work_to_do with two positional arguments -- 67 and
'Bill Johston' -- and whatever key-word arguments were in some_dict.

If you override 'Thread.run', you can define your override to take
whatever parameters you want.

> My current implementation may be ugly. I have a class
>
> class myThread(threading.Thread):
> def __init__(self, func):
> self.func = func
> threading.Thread.__init__(self)
> def run(self):
> print '%s function running' % self.func
> self.func()
[...]

> Is this a good way?

I don't see anything wrong with it, though to me, it seems a
little heavy. To run your func, all you need to do is:

Thread(target=func).start()

Though nine times out of ten, you'd want:

t = Thread(target=func, args=(arg1, arg2, and_so_on))
t.setDaemon(True)
t.start()

If you really need that "print", you could build it into your
'target' function; or you could subclass Thread more generally,
so your subclass adds the print and behaves exactly the same
otherwise. I regard debugging as important, but I do not
believe that this particular print warrants the general
inclusion implied.


Other Pythoners have disagree with me on various matters at
issue here. In particular, others have disagreed with my
advocacy of multiple lines of execution.
 
S

Steve Horsley

Maurice said:
Hi,

I just have a simple question about threads. My classes inherits from
threading.Thread class. I am calling threading.Thread.run() method to
spawn a few threads to parallel some parts of my program. No thread
re-use, pooling, joining ... just plainly spawn a thread, run a routine.

So, at the end of run(), what happens to the thread? Just die?

As far as you are concerned, yes. They really just return to
wherever they came from. How they get created before they call
the run() method, and where they go after run() returns is down
to the implementation of the interpreter. Your code never sees
them before or after.
While I am on it, can threading.Thread.run() accept any parameters?
No. But you can override it in a subclass.
My current implementation may be ugly. I have a class

class myThread(threading.Thread):
def __init__(self, func):
self.func = func
threading.Thread.__init__(self)
def run(self):
print '%s function running' % self.func
self.func()

which is used in

class myClass: #using myThread
def __init__(self): pass
def aFunc(self): pass
def bFunc(self): pass
def runAll(self):
myThread(self.aFunc).start()
myThread(self.bFunc).start()


There is a school of thought that says that a derived object
should never be altered such that it cannot be used as its parent
could. I happen to agree largely with this. Now, your MyThread
implementation is _reducing_ the functionality of its ancestor
Thread object such that you could not use a myThread in place of
a Thread. I believe that you should not be subclassing Thread to
do this. Your myClass doesn't need it anyway. Look at this
modified myClass:

class myClass2:
def aFunc(self): pass
def bFunc(self): pass
def runAll(self):
threading.Thread(target=self.aFunc).start()
threading.Thread(target=self.bFunc).start()


Steve
 
M

Maurice LING

There is a school of thought that says that a derived object should
never be altered such that it cannot be used as its parent could. I
happen to agree largely with this. Now, your MyThread implementation is
_reducing_ the functionality of its ancestor Thread object such that you
could not use a myThread in place of a Thread. I believe that you should
not be subclassing Thread to do this. Your myClass doesn't need it
anyway. Look at this modified myClass:

class myClass2:
def aFunc(self): pass
def bFunc(self): pass
def runAll(self):
threading.Thread(target=self.aFunc).start()
threading.Thread(target=self.bFunc).start()
Thanks everyone. Furthering that, is the following legal?

class myClass3:
def aFunc(self, a): pass
def bFunc(self, b): pass
def runAll(self, a, b):
threading.Thread(target=self.aFunc, args = (a)).start()
threading.Thread(target=self.bFunc, args = (b)).start()

I do have another dumb question which is OT here. Say aFunc method
instantiates a SOAP server that serves forever, will it prevent bFunc
from running as a separate thread?

For example,

class myClass4:
def repeat(self, s): return s+s
def aFunc(self, a):
import SOAPpy
serv = SOAPpy.SOAPServer((a[0], a[1]))
serv.registerFunction(repeat)
serv.serve_forever()
def bFunc(self, b): pass
def runAll(self, a, b):
threading.Thread(target=self.aFunc, args = (a)).start()
threading.Thread(target=self.bFunc, args = (b)).start()

if __name__=='__main__': myClass4().runAll(['localhost', 8000], 'hi')

Will the 2nd thread (bFunc) ever run since the 1st thread is running
forever? Intuitively, I think that both threads will run but I just want
to be doubly sure, because some of my program logic depends on the 2nd
thread running while the 1st thread acts as a SOAP server or something.

Thanks and Cheers
Maurice
 
F

Frithiof Andreas Jensen

I do have another dumb question which is OT here. Say aFunc method
instantiates a SOAP server that serves forever, will it prevent bFunc
from running as a separate thread?

If the SOAP server thread never sleeps or block, it will effectively stop
everything else in your program by eating all the CPU time available. If it
does some IO and other OS functions, probably not because it is likely to
block on those - I do not know SOAPpy in detail, but it being a socket-based
server it should end up in a select loop somewhere. i.e. block when no work
is available. which is what you want.
For example,

class myClass4:
def repeat(self, s): return s+s
def aFunc(self, a):
import SOAPpy
serv = SOAPpy.SOAPServer((a[0], a[1]))
serv.registerFunction(repeat)
serv.serve_forever()
def bFunc(self, b): pass
def runAll(self, a, b):
threading.Thread(target=self.aFunc, args = (a)).start()
threading.Thread(target=self.bFunc, args = (b)).start()

if __name__=='__main__': myClass4().runAll(['localhost', 8000], 'hi')

Will the 2nd thread (bFunc) ever run since the 1st thread is running
forever? Intuitively, I think that both threads will run but I just want
to be doubly sure, because some of my program logic depends on the 2nd
thread running while the 1st thread acts as a SOAP server or something.

Both should run independently, sharing the CPU-time available for your
application. Remember "main" is a thread too, so you will want "main" to
hang around while your threads are running and you will want "main" to block
on something also, thread.join(), time.sleep(), command line parser e.t.c.
whatever is natural.
 
M

Maurice LING

Frithiof said:
I do have another dumb question which is OT here. Say aFunc method
instantiates a SOAP server that serves forever, will it prevent bFunc
from running as a separate thread?


If the SOAP server thread never sleeps or block, it will effectively stop
everything else in your program by eating all the CPU time available. If it
does some IO and other OS functions, probably not because it is likely to
block on those - I do not know SOAPpy in detail, but it being a socket-based
server it should end up in a select loop somewhere. i.e. block when no work
is available. which is what you want.

For example,

class myClass4:
def repeat(self, s): return s+s
def aFunc(self, a):
import SOAPpy
serv = SOAPpy.SOAPServer((a[0], a[1]))
serv.registerFunction(repeat)
serv.serve_forever()
def bFunc(self, b): pass
def runAll(self, a, b):
threading.Thread(target=self.aFunc, args = (a)).start()
threading.Thread(target=self.bFunc, args = (b)).start()

if __name__=='__main__': myClass4().runAll(['localhost', 8000], 'hi')

Will the 2nd thread (bFunc) ever run since the 1st thread is running
forever? Intuitively, I think that both threads will run but I just want
to be doubly sure, because some of my program logic depends on the 2nd
thread running while the 1st thread acts as a SOAP server or something.


Both should run independently, sharing the CPU-time available for your
application. Remember "main" is a thread too, so you will want "main" to
hang around while your threads are running and you will want "main" to block
on something also, thread.join(), time.sleep(), command line parser e.t.c.
whatever is natural.

Somehow I cannot reconcile your replies because I am essentially asking
the same thing and expanding on the original question with an example of
what I am trying to do, but the replies seems contradictory. Do you mind
to explain a bit more?

thanks
Maurice
 
M

Maurice LING

Frithiof said:
I do have another dumb question which is OT here. Say aFunc method
instantiates a SOAP server that serves forever, will it prevent bFunc
from running as a separate thread?


If the SOAP server thread never sleeps or block, it will effectively stop
everything else in your program by eating all the CPU time available. If it
does some IO and other OS functions, probably not because it is likely to
block on those - I do not know SOAPpy in detail, but it being a socket-based
server it should end up in a select loop somewhere. i.e. block when no work
is available. which is what you want.

For example,

class myClass4:
def repeat(self, s): return s+s
def aFunc(self, a):
import SOAPpy
serv = SOAPpy.SOAPServer((a[0], a[1]))
serv.registerFunction(repeat)
serv.serve_forever()
def bFunc(self, b): pass
def runAll(self, a, b):
threading.Thread(target=self.aFunc, args = (a)).start()
threading.Thread(target=self.bFunc, args = (b)).start()

if __name__=='__main__': myClass4().runAll(['localhost', 8000], 'hi')

Will the 2nd thread (bFunc) ever run since the 1st thread is running
forever? Intuitively, I think that both threads will run but I just want
to be doubly sure, because some of my program logic depends on the 2nd
thread running while the 1st thread acts as a SOAP server or something.


Both should run independently, sharing the CPU-time available for your
application. Remember "main" is a thread too, so you will want "main" to
hang around while your threads are running and you will want "main" to block
on something also, thread.join(), time.sleep(), command line parser e.t.c.
whatever is natural.

Somehow I cannot reconcile your replies because I am essentially asking
the same thing and expanding on the original question with an example of
what I am trying to do, but the replies seems contradictory. Do you mind
to explain a bit more?

thanks
Maurice
 
M

Maurice LING

Frithiof said:
I do have another dumb question which is OT here. Say aFunc method
instantiates a SOAP server that serves forever, will it prevent bFunc
from running as a separate thread?


If the SOAP server thread never sleeps or block, it will effectively stop
everything else in your program by eating all the CPU time available. If it
does some IO and other OS functions, probably not because it is likely to
block on those - I do not know SOAPpy in detail, but it being a socket-based
server it should end up in a select loop somewhere. i.e. block when no work
is available. which is what you want.

For example,

class myClass4:
def repeat(self, s): return s+s
def aFunc(self, a):
import SOAPpy
serv = SOAPpy.SOAPServer((a[0], a[1]))
serv.registerFunction(repeat)
serv.serve_forever()
def bFunc(self, b): pass
def runAll(self, a, b):
threading.Thread(target=self.aFunc, args = (a)).start()
threading.Thread(target=self.bFunc, args = (b)).start()

if __name__=='__main__': myClass4().runAll(['localhost', 8000], 'hi')

Will the 2nd thread (bFunc) ever run since the 1st thread is running
forever? Intuitively, I think that both threads will run but I just want
to be doubly sure, because some of my program logic depends on the 2nd
thread running while the 1st thread acts as a SOAP server or something.


Both should run independently, sharing the CPU-time available for your
application. Remember "main" is a thread too, so you will want "main" to
hang around while your threads are running and you will want "main" to block
on something also, thread.join(), time.sleep(), command line parser e.t.c.
whatever is natural.

Somehow I cannot reconcile your replies because I am essentially asking
the same thing and expanding on the original question with an example of
what I am trying to do, but the replies seems contradictory. Do you mind
to explain a bit more?

thanks
Maurice
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top