Search Python Multithreading Ctrl + C exit Problem solution _python

Source: Internet
Author: User
Tags sleep in python

Scene:

You will often experience the following problems: Many IO busy applications take a multithreaded approach, but this time you will find that the Python command line does not respond to ctrl-c, and the corresponding Java code is OK:

Copy Code code as follows:

public class Test {
public static void Main (string[] args) throws Exception {

New Thread (New Runnable () {

public void Run () {
Long start = System.currenttimemillis ();
while (true) {
try {
Thread.Sleep (1000);
catch (Exception e) {
}
System.out.println (System.currenttimemillis ());
if (System.currenttimemillis ()-Start > 1000 *) break;
}
}
). Start ();

}
}
Java Test

CTRL-C will end the program.

and the corresponding Python code:

Copy Code code as follows:

#-*-Coding:utf-8-*-
Import time
Import threading
Start=time.time ()
Def foreverloop ():
Start=time.time ()
While 1:
Time.sleep (1)
Print Time.time ()
If Time.time ()-start>100:
Break

Thread_=threading. Thread (Target=foreverloop)
#thread_. Setdaemon (True)
Thread_.start ()

Python p.py

The ctrl-c is completely out of effect.

Immature analysis:

First of all, setting daemon to True is definitely not the answer. When Daemon is false, after importing the Python line threading actually, threading will check to see if there are any threads that are not daemon after the main thread has been executed, some will wait, the waiting thread is over, and all the signals sent to the main thread will be blocked during the main thread wait. , you can add the signal module in the above code to verify:

Copy Code code as follows:

def sigint_handler (signum,frame):
Print "Main-thread exit"
Sys.exit ()
Signal.signal (signal. Sigint,sigint_handler)

In 100 seconds Press ctrl-c no response, only when the child thread end will appear print "Main-thread exit", can be seen ctrl-c was tested

Action at the end of the main thread in threading:

Copy Code code as follows:

_shutdown = _mainthread (). _exitfunc
def _exitfunc (self):
Self._thread__stop ()
t = _picksomenondaemonthread ()
If T:
If __debug__:
Self._note ("%s:waiting for the other Threads", self)
While T:
T.join ()
t = _picksomenondaemonthread ()
If __debug__:
Self._note ("%s:exiting", self)
Self._thread__delete ()

Join waiting for all daemon threads, in which join can see the source code, and call wait, with the above analysis, the main thread waiting for a lock.

Immature solution:

Only the thread can be set to daemon in order to let the main line does not wait, can accept the ctrl-c signal, but can not let the child thread to end immediately, then only the traditional polling method, using sleep intermittent save point CPU:

Copy Code code as follows:

#-*-Coding:utf-8-*-
Import Time,signal,traceback
Import Sys
Import threading
Start=time.time ()
Def foreverloop ():
Start=time.time ()
While 1:
Time.sleep (1)
Print Time.time ()
If Time.time ()-start>5:
Break

Thread_=threading. Thread (Target=foreverloop)
Thread_.setdaemon (True)
Thread_.start ()

#主线程wait住了, I can't accept the signal.
#thread_. Join ()

Def _exitcheckfunc ():
print "OK"
Try
While 1:
Alive=false
If Thread_.isalive ():
Alive=true
If not alive:
Break
Time.sleep (1)
#为了使得统计时间能够运行, to capture keyboardinterrupt:ctrl-c
Except Keyboardinterrupt, E:
Traceback.print_exc ()
Print "Consume time:", Time.time ()-start

Threading._shutdown=_exitcheckfunc

Cons: Polling always wastes a bit of CPU resources and battery.

Please ask for a better solution.

PS1: Process Monitoring solution:

Use another process to receive the signal and kill the task process, the cow

Copy Code code as follows:

#-*-Coding:utf-8-*-
Import Time,signal,traceback,os
Import Sys
Import threading
Start=time.time ()
Def foreverloop ():
Start=time.time ()
While 1:
Time.sleep (1)
Print Time.time ()
If Time.time ()-start>5:
Break

Class Watcher:
"" "This class solves two problems with multithreaded
Programs in Python, (1) a signal might is delivered
To all thread (which is just a malfeature) and (2) if
The thread that gets the signal is waiting, the signal
is ignored (which is a bug).

The Watcher is a concurrent process (not thread)
Waits for a signal and the process that contains the
Threads. Appendix A of the Little Book of Semaphores.
http://greenteapress.com/semaphores/

I have only tested this on Linux. I would expect it to
Work on the "Macintosh" and "not" work on Windows.
"""

def __init__ (self):
"" "creates a child thread, which returns. The parent
Thread waits for a keyboardinterrupt and then kills
The child thread.
"""
Self.child = Os.fork ()
If Self.child = 0:
Return
Else
Self.watch ()

def watch (self):
Try
Os.wait ()
Except Keyboardinterrupt:
# I put the "capital B" in Keyboardinterrupt I can
# Tell the Watcher gets the SIGINT
print ' Keyboardinterrupt '
Self.kill ()
Sys.exit ()

Def Kill (self):
Try
Os.kill (Self.child, signal. SIGKILL)
Except Oserror:pass

Watcher ()
Thread_=threading. Thread (Target=foreverloop)
Thread_.start ()

Note that watch () must be placed before the thread is created for unknown reason .... , or it will end immediately.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.