question about ctrl-d and atexit with threads

D

Darren Dale

I have a function that stops execution of a thread, and this function
is registered with atexit.register. A simple example module is
included at the end of this post, say its called test.py. If I do the
following in the interactive interpreter, the thread stops executing
as I hoped:

If instead I do the following:

the interpreter hangs up and my_thread continues to execute
indefinitely (confirmed by uncommenting the print statement in run).

I've seen this behavior on python-2.5 and 2.6 on 64 bit linux systems
(gentoo and kubuntu). Can anyone else confirm that invoking ctrl-D
hangs up the interactive interpreter with this code? And if so, could
anyone explain how ctrl-d is different than sys.exit?

Thank you,
Darren

import atexit
import threading
import time


class MyThread(threading.Thread):

def __init__(self):
threading.Thread.__init__(self)

self.lock = threading.Lock()
self.stopEvent = threading.Event()

def run(self):
while not self.stopEvent.isSet():
# print 'running'
time.sleep(0.1)

def stop(self):
self.stopEvent.set()
self.join()


my_thread = MyThread()

def stop_execution():
my_thread.stop()

atexit.register(stop_execution)

my_thread.start()
 
D

Darren Dale

Actually, this problem can also be seen by running this code as a
script, it hangs up if the sys.exit lines are commented, and exits
normally if uncommented.

import atexit
import threading
import time


class MyThread(threading.Thread):

def __init__(self):
threading.Thread.__init__(self)

self.lock = threading.Lock()
self.stopEvent = threading.Event()

def run(self):
while not self.stopEvent.isSet():
time.sleep(0.1)

def stop(self):
self.stopEvent.set()
self.join()


my_thread = MyThread()

def stop_execution():
my_thread.stop()

atexit.register(stop_execution)

my_thread.start()

#import sys
#sys.exit()
 
S

skip

What happens if you simply call

my_thread.setDaemon(True)

(or in Python 2.6):

my_thread.daemon = True

? That is the documented way to exit worker threads when you want the
application to exit. From the threading module docs:

"The entire Python program exits when no alive non-daemon threads are
left."

Skip
 
D

Darren Dale

What happens if you simply call

    my_thread.setDaemon(True)

(or in Python 2.6):

    my_thread.daemon = True

?  That is the documented way to exit worker threads when you want the
application to exit.  From the threading module docs:

    "The entire Python program exits when no alive non-daemon threads are
    left."

Thank you Skip, that solves the problem. I'm still curious what the
difference is between python's handling of sys.exit and EOF, but its
academic at this point.

Thanks again,
Darren
 
G

Gabriel Genellina

Thank you Skip, that solves the problem. I'm still curious what the
difference is between python's handling of sys.exit and EOF, but its
academic at this point.

Some applications open a new window for each document they're handling.
When you close the last window, the application exits ("close" does an
implicit "quit"). Note that this does *not* happen when you close the
first, original document you opened, but when there are no more documents
open. The first document is not special in this regard.

Python threads work the same way; a thread may finish, but as long as
there are other threads alive, the process continues running. Only after
the last thread has finished, the application quits. The main thread *is*
special sometimes, but not in this aspect,
Setting daemon=True is like telling Python "I don't care about this
thread; don't wait for it if that's the only thing you have to do".

Calling sys.exit() is an explicit statement: "I want this program to
finish now" (or as soon as possible). It doesn't wait for the remaining
threads (unless you explicitely do so, like in your code).
 
D

Darren Dale

En Thu, 05 Mar 2009 15:26:18 -0200, Darren Dale <[email protected]>  
escribió:





Some applications open a new window for each document they're handling.  
When you close the last window, the application exits ("close" does an  
implicit "quit"). Note that this does *not* happen when you close the  
first, original document you opened, but when there are no more documents  
open. The first document is not special in this regard.

Python threads work the same way; a thread may finish, but as long as  
there are other threads alive, the process continues running. Only after  
the last thread has finished, the application quits. The main thread *is*  
special sometimes, but not in this aspect,
Setting daemon=True is like telling Python "I don't care about this  
thread; don't wait for it if that's the only thing you have to do".

Calling sys.exit() is an explicit statement: "I want this program to  
finish now" (or as soon as possible). It doesn't wait for the remaining  
threads (unless you explicitely do so, like in your code).

Right, I understand all that. I don't understand how calling sys.exit
at the python command line is different from invoking ctrl-D. They
should both trigger the same mechanism if they are advertised as
equivalent mechanisms for exiting the interpreter, shouldnt they?
 
D

Darren Dale

En Thu, 05 Mar 2009 15:26:18 -0200, Darren Dale <[email protected]>  
escribió:





Some applications open a new window for each document they're handling.  
When you close the last window, the application exits ("close" does an  
implicit "quit"). Note that this does *not* happen when you close the  
first, original document you opened, but when there are no more documents  
open. The first document is not special in this regard.

Python threads work the same way; a thread may finish, but as long as  
there are other threads alive, the process continues running. Only after  
the last thread has finished, the application quits. The main thread *is*  
special sometimes, but not in this aspect,
Setting daemon=True is like telling Python "I don't care about this  
thread; don't wait for it if that's the only thing you have to do".

Calling sys.exit() is an explicit statement: "I want this program to  
finish now" (or as soon as possible). It doesn't wait for the remaining  
threads (unless you explicitely do so, like in your code).

Right, I understand all that. I don't understand how calling sys.exit
at the python command line is different from invoking ctrl-D. They
should both trigger the same mechanism if they are advertised as
equivalent mechanisms for exiting the interpreter, shouldnt they?
 
R

rdmurray

Darren Dale said:
Right, I understand all that. I don't understand how calling sys.exit
at the python command line is different from invoking ctrl-D. They
should both trigger the same mechanism if they are advertised as
equivalent mechanisms for exiting the interpreter, shouldnt they?

First, just to make sure we are on the same page, I assume you
understand that 'ctlr-D' at the python interpreter prompt is
completely equivalent to your example file that does not call
sys.exit before the end of the script file. That is, ctrl-D is
"end of file" for the 'script' you are creating at the
interactive interpreter prompt.

When Gabriel says "as long as there are other threads alive, the
process continues running", that is the key to your question.
The main thread has exited (either the interpreter or your main
script file) but another thread is still running (your child
thread), so Python keeps executing that thread. sys.exit is
_not_ called at the end of the "main" script file, but only after
all threads have exited.

Unless, that is, you call sys.exit explicitly, or set daemon = True.

--RDM
 
D

Darren Dale

First, just to make sure we are on the same page, I assume you
understand that 'ctlr-D' at the python interpreter prompt is
completely equivalent to your example file that does not call
sys.exit before the end of the script file.  That is, ctrl-D is
"end of file" for the 'script' you are creating at the
interactive interpreter prompt.

When Gabriel says "as long as there are other threads alive, the
process continues running", that is the key to your question.
The main thread has exited (either the interpreter or your main
script file) but another thread is still running (your child
thread), so Python keeps executing that thread.  sys.exit is
_not_ called at the end of the "main" script file, but only after
all threads have exited.

Unless, that is, you call sys.exit explicitly, or set daemon = True.

OK, I understand now. Thank you both for the clarification, I learned
something important.
 

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

Forum statistics

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

Latest Threads

Top