项目中经常需要用到多线程,如果一个python程序用了多线程,当子线程没有结束时,用ctrl+c是关闭不了主线程的,这时候就只能用kill命令杀掉,这样会很麻烦。

所以探讨了下怎么ctrl+C关闭多线程python程序,也在网上查了很多别人的做法,自己做了很多实验,尝试了很多种方法,总结得出一个能用的方法就是,把子线程setDeamon(True),通过isAlive方法实现join的功能。

代码:

#encoding=utf-8
__author__ = 'kevinlu1010@qq.com'
import threading
from time import sleep
def f():
sleep(100)
p=threading.Thread(target=f)
p.setDaemon(True)
p.start()
# p.join()
while 1:
if not p.isAlive():
break
sleep(1)
print 'done'

当子线程很多的时候,可以用这个函数

def threads_join(threads):
'''
令主线程阻塞,等待子线程执行完才继续,使用这个方法比使用join的好处是,可以ctrl+c kill掉进程
'''
for t in threads:
while 1:
if t.isAlive():
sleep(10)
else:
break

这种做法的坏处就是令主线程阻塞,直到子线程执行完这个功能的实现太麻烦了,原本用join来实现就好方便很多

下面是研究的过程中的尝试,但是全部都实现不了ctrl+C关闭的功能

原始的多线程程序

def f():
sleep(100)
p=threading.Thread(target=f)
p.start()
p.join() print 'done'

这是最原始的一个多线程程序。

尝试一:设置线程为守护线程,即加入

p.setDaemon(True)

但是ctrl+c,程序没反应,跟没加是一样的

尝试二:使用信号,因为ctrl c的时候系统会向程序发送sigint信号,所以我们可以令程序捕获这个信号,并调用os的kill方法杀死自己

import signal
import os
import threading
from time import sleep
def f(a,b):
print 'kill me'
os.kill(os.getpid(),signal.SIGKILL) def tf():
sleep(20) signal.signal(signal.SIGINT,f)
p=threading.Thread(target=tf)
p.start()
p.join() print 'done'

程序运行后,我立刻按ctrl c ,主线程会等子线程sleep20后,才会print 'kill me',证明主线程在等待子线程执行的时候,即join的时候,是捕获不了系统发来的信号的,要等子线程执行完毕,才能捕获。所以这个方法还是不行。

尝试三,用一个标志来让子线程自己结束自己的运行

is_exit=0
def f(a,b):
global is_exit
is_exit=1
print 'kill me'
os.kill(os.getpid(),signal.SIGKILL) def tf():
while not is_exit:
sleep(20) signal.signal(signal.SIGINT,f)
p=threading.Thread(target=tf)
p.start()
while 1:
sleep(10) print 'done'

这里加入一个标志is_exit用来标志子线程是否继续执行,然后加入信号,当捕获关闭信号时,把is_exit改为1,令到子线程自己结束,由于主线程在join的状态下是接受不了信号的,所以这里让主线程处于一直等待的状态。

这个做法是能做到ctrl c关闭子线程的,缺点就是子线程需要做完一个循环才能结束,同时主线程没有了join的功能,适用于主线程在给子线程发放任务后就不需要做任何操作的情形。

所以总的来说,ctrl c不能关闭多线程的程序的主要原因是使用了join方法,一旦用了join,主线程就会一直处于阻塞状态,不接受任何外界的联系。但是join方法在实际的业务中是经常需要用到的,我查了很久也没有查到可以替代join的,同时可以被ctrl c的方法。上面第一个程序用到的使用alive方法来实现join的功能的做法算是一个不太好,但又不能不使用它的解决方案了,希望后面能找到更好的实现join功能的方法。

ctrl+c关闭多线程python程序的更多相关文章

  1. sublime text3点击ctrl+B无法运行Python程序?

    1.打开sublime text 3 ,选择 tools-->Build System-->New Build System.... 2.将下面代码块复制进新文件中,并命名为Python. ...

  2. 使用Notepad++编译运行C/C++/Python程序

    对我来说,比较常用的是C/C++/Python. 使用Notepad++编译运行单个源文件的C/C++/Python,比使用复杂的IDE更加快捷. 想要让Notepad++能够做到编译运行C/C++/ ...

  3. Notepad++编写运行python程序

    Notepad++编写运行python程序. 1.菜单栏->语言->P->Python设置语言为Python 2.写好代码后ctrl+s保存文件为py文件 3.菜单栏->运行, ...

  4. 第一阶段——CentOS6_Python3.6.1笔记(尚学堂-Python基础快速入门)+ 【补充】麦子-Python程序入门与进阶

    虚拟机环境: 设置网络 .修改网络地址 .设置网卡为nat模式 .确保物理机启动dhcp.net服务 .编辑文件:vim /etc/sysconfig/network-scripts/ifcfg-et ...

  5. 如何优雅地退出python程序

    如何优雅地退出python程序 一个单模的python程序,启动之后要能够优雅地关闭.即当用户按Ctrl+C或者kill pid的时候,程序都能从容关闭.实现起来非常简单. is_running = ...

  6. 如何在交互式环境中执行Python程序

    相信接触过Python的小伙伴们都知道运行Python脚本程序的方式有多种,目前主要的方式有:交互式环境运行.命令行窗口运行.开发工具上运行等,其中在不同的操作平台上还互不相同.今天,小编讲些Pyth ...

  7. [.net 面向对象程序设计进阶] (17) 多线程(Multithreading)(二) 利用多线程提高程序性能(中)

    [.net 面向对象程序设计进阶] (17) 多线程(Multithreading)(二) 利用多线程提高程序性能(中) 本节要点: 上节介绍了多线程的基本使用方法和基本应用示例,本节深入介绍.NET ...

  8. [.net 面向对象程序设计进阶] (16) 多线程(Multithreading)(一) 利用多线程提高程序性能(上)

    [.net 面向对象程序设计进阶] (16) 多线程(Multithreading)(一) 利用多线程提高程序性能(上) 本节导读: 随着硬件和网络的高速发展,为多线程(Multithreading) ...

  9. Python程序的常见错误(收集篇)

    关于Python Python是一门解释性的,面向对象的,并具有动态语义的高级编程语言.它高级的内置数据结构,结合其动态类型和动态绑定的特性,使得它在快速应用程序开发(Rapid Applicatio ...

随机推荐

  1. Vmware中为Mac Os安装vmtools

    成功方法: 1. 在VMWare中点击edit this virtual machine 2. 添加CD/DVD,使用iso,找到那个darwin.iso 3. 在setting里面,点击CD/DVD ...

  2. Android市场官方的统计信息

    做Android应用和游戏,避免不了的要了解市面上的各种android设备的信息,以最大程度的兼容更多的设备. Android市场会定期发布统计信息,包括SDK版本,屏幕大小和分辨率,OpenGL E ...

  3. Events

    Events The idea behind Events is the ability to send data, as parameters, to interested Listeners an ...

  4. USB HID usage table

    This usage table lets usbhidctl decode the HID data correctly for the APC RS/XS1000's. This work was ...

  5. Oracle批量加注释,并生成html

    excel连接列名生成oracle注释 notes: A2为列名,B2为注释 ="comment on column ColAgreementHeader."&A2& ...

  6. sql基本语法:

    1.create database db_name; --创建数据库 2.drop database db_name;  --删除数据库 3.show create database db_name\ ...

  7. LINQ to Entities 不支持 LINQ 表达式节点类型“Invoke”

    解决方法即 where后加 .Compile()

  8. java.lang.RuntimeException: Unable to instantiate activity ComponentInfo异常总结

    java.lang.RuntimeException: Unable to instantiate activity ComponentInfo异常总结 做android开发的可能都碰到"j ...

  9. redhat6.5 配置使用centos的yum源

    新安装了redhat6.5安装后,登录系统,使用yum update 更新系统.提示: This system is not registered to Red Hat Subscription Ma ...

  10. 再跟SQL谈一谈--高级篇(一)

    1.SELECT KEYWORD ①TOP ②LIKE ③IN ④BETWEEN...AND ⑤ALIAS 2.SELECT JOIN ①JOIN | INNER JOIN ②LEFT JOIN ③R ...