Exit a process while threads are sleeping - python

In a python script, I started a bunch of threads, each of which pulls some resource at an interval using time.sleep(interval). I have another thread running, which uses the cmd module to monitor user inputs. When the user enters 'q', I call
sys.exit(0)
However, when the script is running and I enter 'q', the thread user input monitoring thread is quit, but the sleeping threads are still alive. (meaning the program does not exit)
I'm wondering if I'm doing it the right way?

sys.exit will only stop the thread it executes from. If you have other non-daemon thread in your program they will continue to execute. Section 17.2.1 of the Python library docs contains:
A thread can be flagged as a “daemon
thread”. The significance of this flag
is that the entire Python program
exits when only daemon threads are
left. The initial value is inherited
from the creating thread. The flag can
be set through the daemon property.
See also Why does sys.exit() not exit when called inside a thread in Python?.

Related

python function not running as thread

this is done in python 2.7.12
serialHelper is a class module arround python serial and this code does work nicely
#!/usr/bin/env python
import threading
from time import sleep
import serialHelper
sh = serialHelper.SerialHelper()
def serialGetter():
h = 0
while True:
h = h + 1
s_resp = sh.getResponse()
print ('response ' + s_resp)
sleep(3)
if __name__ == '__main__':
try:
t = threading.Thread(target=sh.serialReader)
t.setDaemon(True)
t.start()
serialGetter()
#tSR = threading.Thread(target=serialGetter)
#tSR.setDaemon(True)
#tSR.start()
except Exception as e:
print (e)
however the attemp to run serialGetter as thread as remarked it just dies.
Any reason why that function can not run as thread ?
Quoting from the Python documentation:
The entire Python program exits when no alive non-daemon threads are left.
So if you setDaemon(True) every new thread and then exit the main thread (by falling off the end of the script), the whole program will exit immediately. This kills all of the threads. Either don't use setDaemon(True), or don't exit the main thread without first calling join() on all of the threads you want to wait for.
Stepping back for a moment, it may help to think about the intended use case of a daemon thread. In Unix, a daemon is a process that runs in the background and (typically) serves requests or performs operations, either on behalf of remote clients over the network or local processes. The same basic idea applies to daemon threads:
You launch the daemon thread with some kind of work queue.
When you need some work done on the thread, you hand it a work object.
When you want the result of that work, you use an event or a future to wait for it to complete.
After requesting some work, you always eventually wait for it to complete, or perhaps cancel it (if your worker protocol supports cancellation).
You don't have to clean up the daemon thread at program termination. It just quietly goes away when there are no other threads left.
The problem is step (4). If you forget about some work object, and exit the app without waiting for it to complete, the work may get interrupted. Daemon threads don't gracefully shut down, so you could leave the outside world in an inconsistent state (e.g. an incomplete database transaction, a file that never got closed, etc.). It's often better to use a regular thread, and replace step (5) with an explicit "Finish up your work and shut down" work object that the main thread hands to the worker thread before exiting. The worker thread then recognizes this object, stops waiting on the work queue, and terminates itself once it's no longer doing anything else. This is slightly more up-front work, but is much safer in the event that a work object is inadvertently abandoned.
Because of all of the above, I recommend not using daemon threads unless you have a strong reason for them.

How to return a process id of a lengthy process started using Thread in python before the thread completes its execution

How can I return a process id of a lengthy process started using Thread in Python before the thread completes its execution?
I'm using Tkinter GUI so I can't start a lengthy process on the main thread so instead I start one on a separate thread.
The thread in turn calls subprocess.popen. This process should run for like 5 -6 hours.
But When I press stopbutton I need this process to stop but I am unable to return the process id of the process created using subprocess.popen.
Is there any solution to this?
If you are using subprocess.Popen simply to spin off another process, there is no reason you need to do so from another thread. A sub-process created this way does not block your main thread. You can continue to do other things while the sub-process is running. You simply keep a reference to the Popen object returned.
The Popen object has all the facilities you need for monitoring / interacting with the sub-process. You can read and write to its standard input and output (via stdin and stdout members, if created with PIPE); you can monitor readability / writability of stdin and stdout (with select module); you can check whether the sub-process is still in existence with poll, reap its exit status with wait; you can stop it with terminate (or kill depending on how emphatic you wish to be).
There are certainly times when it might be advantageous to do this from another thread -- for example, if you need significant interaction with the sub-process and implementing that in the main thread would over-complicate your logic. In that case, it would be best to arrange a mechanism whereby you signal to your other "monitoring" thread that it's time to shutdown and allow the monitoring thread to execute terminate or kill on the sub-process.

What does sys.exit really do with multiple threads?

I was really confused by sys.exit() in python.
In python documentation, it says "Exit from Python"; does that mean when sys.exit() is called in a python program, the process will exit? If so, the code below shows a different result:
import sys
import time
import threading
def threadrun():
while(True):
time.sleep(1)
if __name__=="__main__":
t=threading.Thread(target=threadrun)
t.start()
sys.exit()
Launching this program in linux, result was not the expected one as python documentation says but still run in the system, so what does sys.exit() really do?
(Paraphrasing what's in the Python 2 documentation for Thread Objects)
Normally a Python program exits only when there's nothing but daemon✶
threads (ignoring itself) left running. The “main thread” object which corresponds to the initial thread of control in the program isn't a daemon thread. Threads created using threading.Thread inherit their daemonic status from the creating thread, so if that's the main thread, they will also be non-daemonic.
This means that by default any threads created and started by your main program will prevent it from exiting if they are still running when the main thread is terminated (by sys.exit() or simply by just hitting the end of its code). In other words, the program exits only when no alive non‑daemon threads (i.e. only daemon threads) are left.
You can override this default behavior by explicitly setting✶✶ the
daemon property of any
created thread objects to True before starting it.
if __name__=="__main__":
t = threading.Thread(target=threadrun)
t.daemon = True # Explicitly set property.
t.start()
sys.exit()
Which will allow the program to actually end when sys.exit() is called (although calling it explicitly like that would not be necessary since presumably the code above would be at the end of the script anyway).
✶ A daemon thread is one that runs in the background and does not prevent the interpreter from exiting. See Daemon Threads Explanation.
✶✶ In Python 3.3, a daemon keyword argument with a default value of None was added to the Thread
class constructor
which means that, starting from that version onwards, you can simply use:
# Sets whether the thread is daemonic via "daemon" keyword argument.
t = threading.Thread(target=threadrun, daemon=True)
However, doing it separately via an explicit attribute assignment statement
still works, and would therefore be the more version-portable way of
doing it.
As per the documentation sys.exit() raises SystemExit:
Exit the interpreter by raising SystemExit(status).
If SystemExit reaches the default exception handler,
it calls handle_system_exit(), which more or less pushes through to Py_Finalize(), which in turn calls wait_for_thread_shutdown() in Python 2, so sys.exit() is the same as the normal falling off the bottom of the main module in waiting for all non-daemon threads to terminate.
In your case, the end of the program is when the last thread will be terminated. Maybe kind of join() method(like in Java) in python will wait for other threads.
Please, read this article(: there is a good explanation how to play with threads in your case
Use of threading.Thread.join()
and
documentation
https://docs.python.org/2/library/threading.html (but relax, it is only for additional knowledge.
and read this article about daemon property(if you do not want to wait for others threads become terminated
Meaning of daemon property on Python Threads

Meaning of daemon property on Python Threads

I'm a little confused about what setting a thread to be a daemon means.
The documentation says this:
A thread can be flagged as a “daemon
thread”. The significance of this flag
is that the entire Python program
exits when only daemon threads are
left. The initial value is inherited
from the creating thread. The flag can
be set through the daemon property.
I'm not sure what makes this different from a normal thread.
Is this saying that this program won't ever finish?
def threadfunc():
while True:
time.sleep(1)
threading.Thread(target=threadfunc).start()
Even though the main thread finishes it's execution. While will finish immediately?
def threadfunc():
while True:
time.sleep(1)
th = threading.Thread(target=threadfunc)
th.daemon = True
th.start()
I ask because I have a situation where in my main thread I'm calling sys.exit(), and the process just hangs and my other threads are running as I can see the log.
Does this have anything to do with sys.exit() being called with threads alive?
Is this saying that this program won't ever finish?
Yes, that program won't finish, just try it out.
I ask because I have a situation where
in my main thread I'm calling
sys.exit(), and the process just hangs
and my other threads are running as I
can see the log. Does this have
anything to do with sys.exit() being
called with threads alive?
Yes, even exit won't stop other threads, it simply raises SystemExit in the main thread. So while the main thread will stop (just like it does on any other unhandled Exception), all other non-daemonic threads will continue to work.
Setting thread.daemon = True will allow the main program to exit. Apps normally wait till all child threads are finished before completing.
th.daemon = True #set this thread as a Daemon Thread
You can think in a Daemon thread as a service this means that it will be running in the background of your computer doing differents task, like indexing files, parsing xml, retrieving news etc, anything that is a long running process.
Your Main thread will finish and your daemon will still be running in the background, that is the reason why your program aka Main thread finish, if you want just put an infinite loop and you will see your thread still running.
An example for a daemon thread is the garbage collection.

What difference it makes when I set python thread as a Daemon

What difference makes it when I set a python thread as a daemon, using thread.setDaemon(True)?
A daemon thread will not prevent the application from exiting. The program ends when all non-daemon threads (main thread included) are complete.
So generally, if you're doing something in the background, you might want to set the thread as daemon so you don't have to explicitly have that thread's function return before the app can exit.
For example, if you are writing a GUI application and the user closes the main window, the program should quit. But if you have non-daemon threads hanging around, it won't.
From the docs: http://docs.python.org/library/threading.html#threading.Thread.daemon
Its initial value is inherited from
the creating thread; the main thread
is not a daemon thread and therefore
all threads created in the main thread
default to daemon = False.
The entire Python program exits when
no alive non-daemon threads are left.

Categories

Resources