No threading.start_new_thread(), useful addition?

29 views
Skip to first unread message

Ulrich Eckhardt

unread,
Oct 8, 2009, 3:17:58 AM10/8/09
to
Hi!

I'm looking at the 'threading' module and see that other than the 'thread'
module it doesn't have a simple function to start a new thread. Instead,
you first have to instantiate a threading object and then start the new
thread on it:

t = threading.Thread(target=my_function)
t.start()

What I'm wondering is if following function wouldn't be a good addition to
the threading module:

def start_new_thread(target, ..):
t = Thread(target, ..)
t.start()
return t

Note: I left out the additional parameters for brevity, but they should of
course be forwarded, but the 'target' parameter is not optional as it is
with Thread's constructor.

Uli

--
Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932

Laszlo Nagy

unread,
Oct 8, 2009, 6:42:55 AM10/8/09
to Ulrich Eckhardt, pytho...@python.org
Ulrich Eckhardt írta:

> Hi!
>
> I'm looking at the 'threading' module and see that other than the 'thread'
> module it doesn't have a simple function to start a new thread. Instead,
> you first have to instantiate a threading object and then start the new
> thread on it:
>
> t = threading.Thread(target=my_function)
> t.start()
>
> What I'm wondering is if following function wouldn't be a good addition to
> the threading module:
>
> def start_new_thread(target, ..):
> t = Thread(target, ..)
> t.start()
> return t
What is wrong with thread.start_new_thread ? At least it supports
function arguments. Your suggested addition would only useful if you
want to start argument-less functions in separate threads, from multiple
places in a module. This is quite special, not general enough to make
the suggested change. You can use this one-liner:

import threading.Thread as thr

thr(target=my_function).start()


But really thread.start_new_thread is better:

import thread.start_new_thread as thr

thr(my_function,arg1,arg2)

Best,

Laci


sturlamolden

unread,
Oct 8, 2009, 7:18:55 AM10/8/09
to
On 8 Okt, 09:17, Ulrich Eckhardt <eckha...@satorlaser.com> wrote:

> I'm looking at the 'threading' module and see that other than the 'thread'
> module it doesn't have a simple function to start a new thread. Instead,
> you first have to instantiate a threading object and then start the new
> thread on it:
>
>   t = threading.Thread(target=my_function)
>   t.start()

One usually want to subclass threading.Thread instead of specifying a
target function.

class mythread(threading.Thread):

def run():
# whatever
pass

t = mythread()
t.start()

Also, you may want to set the daemon flag before starting the thread,
which is why the thread is created in a suspended state.

Christian Heimes

unread,
Oct 8, 2009, 7:24:14 AM10/8/09
to pytho...@python.org
Laszlo Nagy wrote:
> But really thread.start_new_thread is better:
>
> import thread.start_new_thread as thr
>
> thr(my_function,arg1,arg2)

Please don't use the thread module directly, especially the
start_new_thread function. It a low level function that bypasses the
threading framework. The is no good reason to use this function in favor
of threading.Thread().

Christian

Ulrich Eckhardt

unread,
Oct 8, 2009, 8:10:06 AM10/8/09
to
Laszlo Nagy wrote:
> Ulrich Eckhardt írta:
>> Hi!
>>
>> I'm looking at the 'threading' module and see that other than the
>> 'thread' module it doesn't have a simple function to start a new thread.
>> Instead, you first have to instantiate a threading object and then start
>> the new thread on it:
>>
>> t = threading.Thread(target=my_function)
>> t.start()
>>
>> What I'm wondering is if following function wouldn't be a good addition
>> to the threading module:
>>
>> def start_new_thread(target, ..):
>> t = Thread(target, ..)
>> t.start()
>> return t
> What is wrong with thread.start_new_thread ?

The 'thread' module is more or less deprecated.

> At least it supports function arguments. Your suggested addition would
> only useful if you want to start argument-less functions in separate
> threads, from multiple places in a module.

To quote from my own posting:


| Note: I left out the additional parameters for brevity, but they
| should of course be forwarded, but the 'target' parameter is not
| optional as it is with Thread's constructor.

No, this is supposed to support function arguments, too.

> You can use this one-liner:
>
> import threading.Thread as thr
>
> thr(target=my_function).start()

No, as this one doesn't give me a handle to the thread. I also find this
barely readable, for sure it doesn't beat the readability of the proposed
function.

Ulrich Eckhardt

unread,
Oct 8, 2009, 8:03:46 AM10/8/09
to
sturlamolden wrote:
> On 8 Okt, 09:17, Ulrich Eckhardt <eckha...@satorlaser.com> wrote:
>
>> I'm looking at the 'threading' module and see that other than the
>> 'thread' module it doesn't have a simple function to start a new thread.
>> Instead, you first have to instantiate a threading object and then start
>> the new thread on it:
>>
>> t = threading.Thread(target=my_function)
>> t.start()
>
> One usually want to subclass threading.Thread instead of specifying a
> target function.

No. You also don't derive from a file class in order to read a file. The
point is that the Thread instance is not a thread but it is an object that
can be used to access a thread, similar to a File instance which file which
is not the file but just an object to access one.

I personally find it much cleaner this way. Also, why should any code care
in which thread it is executed? Why should I have to derive a class from
some other only because I want to run one of its functions in a separate
thread?

I don't want to start a discussion which principle is better, that would
only end in endless discussions, but I'd like to point out that the
principle of deriving from a thread class is not universally accepted. ;)

Cheers!

Hendrik van Rooyen

unread,
Oct 8, 2009, 11:16:39 AM10/8/09
to pytho...@python.org

I have seen this advice a couple of times now, and I do not understand it.

From my perspective (which is admittedly jaundiced) Threading just adds a
bunch of superfluous stuff like a run method and other weird things that I
cannot see a need for.

The simplicity of this kind of code:

def this_is_a_thread(arg1,arg2):
do_some_initialisation(arg1,arg2)
while some_condition:
do_some_stuff()

which then gets started with thread.start_new_thread, does it for me.

What does the Threading module buy me, other than a formal OO approach?

- Hendrik

Christian Heimes

unread,
Oct 8, 2009, 11:33:54 AM10/8/09
to Hendrik van Rooyen, pytho...@python.org
Hendrik van Rooyen wrote:
> What does the Threading module buy me, other than a formal OO approach?

* the interpreter won't know about your thread when you bypass the
threading module and use the thread module directly. The thread isn't in
the list of active threads and the interpreter is unable to wait for the
thread to exit when Python shuts down. All threads created by the thread
module behave like daemonic threads.

* exception reporting doesn't work with thread.start_new_thread

* profiling and tracing doesn't work with thread.start_new_thread

* introspection of active thread doesn't work because threads started by
thread.start_new_thread are invisible for the rest of the interpreter

* you have to roll your own system to join a thread

* probably more stuff

In Python 3.0 the thread module has been renamed to _thread in order to
reflect the nature of the C extension.

Christian

Christian Heimes

unread,
Oct 8, 2009, 11:35:57 AM10/8/09
to pytho...@python.org
Ulrich Eckhardt wrote:
> No, as this one doesn't give me a handle to the thread. I also find this
> barely readable, for sure it doesn't beat the readability of the proposed
> function.

Roll your own convenient function, though. :) At work we have this short
function in our tool box:

def daemonthread(target, name=None, autostart=True, args=(), kwargs=None):
"""Start a thread as daemonic thread
"""
thread = Thread(target=target, name=name, args=args, kwargs=kwargs)
thread.setDaemon(True)
if autostart:
thread.start()
return thread

Christian

Laszlo Nagy

unread,
Oct 9, 2009, 12:06:03 PM10/9/09
to Ulrich Eckhardt, pytho...@python.org

> I personally find it much cleaner this way. Also, why should any code care
> in which thread it is executed? Why should I have to derive a class from
> some other only because I want to run one of its functions in a separate
> thread?
>
>
I think you are right! Especially that you can (and probably will) call
other methods from your thread. For example, functions from the standard
library. Or use methods of objects that where created in a different
thread. I think we can say, you must call methods of other (not Thread)
objects if you ever want to do something useful in your thread.

Now I'm beginnig to agree with you, Ulrich. We have
threading.enumerate() - it can be used to list active threads. So if you
only want to start a function in a separate thread, then you do not
really need the Thread object. Then we do you HAVE TO create a Thread
object explicitely?

Of course you can easily create a nice decorator like this:

import threading
def threadlaunch(func):
def launcher(*args,**kwargs):
thr = threading.Thread(target=func,args=args,kwargs=kwargs)
thr.start()
return thr
return launcher

And then do something like:

import time
@threadlaunch
def print_something(w,s):
print "please wait..."
time.sleep(w)
print s
thr = print_something(3,"Test")
print "started print_something in",thr

How about that? (Or was it your concern that it is not part of the
standard library?)

Best,

Laszlo

Carl Banks

unread,
Oct 9, 2009, 4:35:05 PM10/9/09
to
On Oct 8, 5:03 am, Ulrich Eckhardt <eckha...@satorlaser.com> wrote:
> sturlamolden wrote:
> > On 8 Okt, 09:17, Ulrich Eckhardt <eckha...@satorlaser.com> wrote:
>
> >> I'm looking at the 'threading' module and see that other than the
> >> 'thread' module it doesn't have a simple function to start a new thread.
> >> Instead, you first have to instantiate a threading object and then start
> >> the new thread on it:
>
> >> t = threading.Thread(target=my_function)
> >> t.start()
>
> > One usually want to subclass threading.Thread instead of specifying a
> > target function.
>
> No. You also don't derive from a file class in order to read a file. The
> point is that the Thread instance is not a thread but it is an object that
> can be used to access a thread, similar to a File instance which file which
> is not the file but just an object to access one.
>
> I personally find it much cleaner this way. Also, why should any code care
> in which thread it is executed? Why should I have to derive a class from
> some other only because I want to run one of its functions in a separate
> thread?

I have to agree. I've been trying to understand some other entity's
Java code lately, and it's mondo-confusing because there is a subclass
of Thread that has methods that are called from other threads. To
make matters worse the variable this method is assigned to is called,
simply, "thread".

As far as I can discern doing that way (as opposed to using a Runnable
object) didn't have any effect except to make the logic harder to
understand.

So (getting back to Python) count me among those who say one usally
want to specify a target function instead of subclassing
threading.Thread.


Carl Banks

Christian Heimes

unread,
Oct 9, 2009, 6:45:21 PM10/9/09
to Laszlo Nagy, python list
Laszlo Nagy wrote:
> IMHO it is much cleaner to implement this as a decorator. Pro:
> transparent passing of positional and keyword arguments, keeps function
> documentation.

You are entitled to your opinion but I STRONGLY recommend against your
decorator. You MUST NOT start threads a a side effect of a module
import. It can lead to severe bugs and dead lock the entire interpreter.
I'm speaking as an experienced Python developer and a CPython core
developer. Please trust me in this. The interaction between the import
system, its global import lock and threads can and will lead to
surprising and hard to debug bugs. A well designed application loads its
modules first and then initializes its components explicitly. You don't
want to fire up threads randomly!

Christian

Ethan Furman

unread,
Oct 9, 2009, 6:57:52 PM10/9/09
to python list

Okay, I for one will never start threads as a side-effect of module import.

Other than that, are there other inherent problems with using that
decorator at non-import times?

~Ethan~

Laszlo Nagy

unread,
Oct 10, 2009, 5:42:03 AM10/10/09
to Christian Heimes, python-list (General)
Christian Heimes wote:

> Laszlo Nagy wrote:
>
>> IMHO it is much cleaner to implement this as a decorator. Pro:
>> transparent passing of positional and keyword arguments, keeps function
>> documentation.
>>
>
> You are entitled to your opinion but I STRONGLY recommend against your
> decorator. You MUST NOT start threads as a side effect of a module
> import.
That decorator will not start threads at module import time, except if
you call the decorated function at module import time. I trust your
opinion, and I won't call such decorated functions at import time. :-)

L

Carl Banks

unread,
Oct 10, 2009, 7:19:57 PM10/10/09
to
On Oct 9, 3:45 pm, Christian Heimes <li...@cheimes.de> wrote:
> Laszlo Nagy wrote:
> > IMHO it is much cleaner to implement this as a decorator. Pro:
> > transparent passing of positional and keyword arguments, keeps function
> > documentation.
>
> You are entitled to your opinion but I STRONGLY recommend against your
> decorator. You MUST NOT start threads a a side effect of a module
> import.

His decorator doesn't do that (necesarily).

His example code did that, but I took it to be an example script, and
it's kind of hard to run code that's not a side effect of importing
__main__.


Carl Banks

Reply all
Reply to author
Forward
0 new messages