python中强制关闭线程、协程、进程方法

原创 羽林君 2022-11-27 19:57

前言

python使用中多线程、多进程、多协程使用是比较常见的。那么如果在多线程等的使用,我们这个时候我们想从外部强制杀掉该线程请问如何操作?下面我就分享一下我的执行看法:

作者:良知犹存

转载授权以及围观:欢迎关注微信公众号:羽林君

或者添加作者个人微信:become_me


需求

在python多线程等的使用中,我们需要在外部强制终止线程,这个时候又没有unix的pthread kill的函数,多进程这个时候大家觉得可以使用kill -9 直接强制杀掉就可以了,从逻辑上这么做没问题,但是不太优雅。其中我总结了一下不仅是使用多线程,以及多协程、多进程在python的实现对比。

此外也可以参考stackoverlow的文章,如何优雅的关闭一个线程,里面有很多的讨论,大家可以阅读一下

下面是网址:https://stackoverflow.com/questions/323972/is-there-any-way-to-kill-a-thread

开始进入正题:

多线程

首先线程中进行退出的话,我们经常会使用一种方式:子线程执行的循环条件设置一个条件,当我们需要退出子线程的时候,将该条件置位,这个时候子线程会主动退出,但是当子线程处于阻塞情况下,没有在循环中判断条件,并且阻塞时间不定的情况下,我们回收该线程也变得遥遥无期。这个时候就需要下面的几种方式出马了:

守护线程:

如果你设置一个线程为守护线程,就表示你在说这个线程是不重要的,在进程退出的时候,不用等待这个线程退出。如果你的主线程在退出的时候,不用等待那些子线程完成,那就设置这些线程的daemon属性。即,在线程开始(thread.start())之前,调用setDeamon()函数,设定线程的daemon标志。(thread.setDaemon(True))就表示这个线程“不重要”。

如果你想等待子线程完成再退出,那就什么都不用做。,或者显示地调用thread.setDaemon(False),设置daemon的值为false。新的子线程会继承父线程的daemon标志。整个Python会在所有的非守护线程退出后才会结束,即进程中没有非守护线程存在的时候才结束。

也就是子线程为非deamon线程,主线程不立刻退出

import threading
import time
import gc
import datetime

def circle():
    print("begin")
    try:
        while True:
            current_time = datetime.datetime.now()
            print(str(current_time) + ' circle.................')
            time.sleep(3)
    except Exception as e:
        print('error:',e)
    finally:
        print('end')


if __name__ == "__main__":
   t = threading.Thread(target=circle)
   t.setDaemon(True)
   t.start()
   time.sleep(1)
   # stop_thread(t)
   # print('stoped threading Thread') 
   current_time = datetime.datetime.now()
   print(str(current_time) + ' stoped after'
   gc.collect()
   while True:
      time.sleep(1)
      current_time = datetime.datetime.now()
      print(str(current_time) + ' end circle'

是否是主线程进行控制?

守护线程需要主线程退出才能完成子线程退出,下面是代码,再封装一层进行验证是否需要主线程退出

def Daemon_thread():
   circle_thread= threading.Thread(target=circle)
#    circle_thread.daemon = True
   circle_thread.setDaemon(True)
   circle_thread.start()   
   while running:
        print('running:',running) 
        time.sleep(1)
   print('end..........'


if __name__ == "__main__":
    t = threading.Thread(target=Daemon_thread)
    t.start()   
    time.sleep(3)
    running = False
    print('stop running:',running) 
    print('stoped 3'
    gc.collect()
    while True:
        time.sleep(3)
        print('stoped circle'

替换main函数执行,发现打印了 stoped 3这个标志后circle线程还在继续执行。

结论:处理信号靠的就是主线程,只有保证他活着,信号才能正确处理。

在 Python 线程中引发异常

虽然使用PyThreadState_SetAsyncExc大部分情况下可以满足我们直接退出线程的操作;但是PyThreadState_SetAsyncExc方法只是为线程退出执行“计划”。它不会杀死线程,尤其是当它正在执行外部 C 库时。尝试sleep(100)用你的方法杀死一个。它将在 100 秒后被“杀死”。while flag:它与->flag = False方法一样有效。

所以子线程有例如sleep等阻塞函数时候,在休眠过程中,子线程无法响应,会被主线程捕获,导致无法取消子线程。就是实际上当线程休眠时候,直接使用async_raise 这个函数杀掉线程并不可以,因为如果线程在 Python 解释器之外忙,它就不会捕获中断

示例代码:

import ctypes
import inspect
import threading
import time
import gc
import datetime

def async_raise(tid, exctype):
   """raises the exception, performs cleanup if needed"""
   tid = ctypes.c_long(tid)
   if not inspect.isclass(exctype):
      exctype = type(exctype)
   res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))
   if res == 0:
      raise ValueError("invalid thread id")
   elif res != 1:
      # """if it returns a number greater than one, you're in trouble,  
      # and you should call it again with exc=NULL to revert the effect"""  
      ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
      raise SystemError("PyThreadState_SetAsyncExc failed")
      
def stop_thread(thread):
   async_raise(thread.ident, SystemExit)
   
def circle():
    print("begin")
    try:
        while True:
            current_time = datetime.datetime.now()
            print(str(current_time) + ' circle.................')
            time.sleep(3)
    except Exception as e:
        print('error:',e)
    finally:
        print('end')

if __name__ == "__main__":
   t = threading.Thread(target=circle)
   t.start()
   time.sleep(1)
   stop_thread(t)
   print('stoped threading Thread'
   current_time = datetime.datetime.now()
   print(str(current_time) + ' stoped after'
   gc.collect()
   while True:
      time.sleep(1)
      current_time = datetime.datetime.now()
      print(str(current_time) + ' end circle'

signal.pthread_kill操作:

这个是最接近与 unix中pthread kill操作,网上看到一些使用,但是自己验证时候没有找到这个库里面的使用,

这是在python官方的signal解释文档里面的描述,看到是3.3 新版功能,我自己本身是python3.10,没有pthread_kill,可能是后续版本又做了去除。

这是网上看到的一些示例代码,但是没法执行,如果有人知道使用可以进行交流。

from signal import pthread_kill, SIGTSTP
from threading import Thread
from itertools import count
from time import sleep

def target():
    for num in count():
        print(num)
        sleep(1)

thread = Thread(target=target)
thread.start()
sleep(5)
signal.pthread_kill(thread.ident, SIGTSTP)

多进程

multiprocessing 是一个支持使用与 threading 模块类似的 API 来产生进程的包。multiprocessing 包同时提供了本地和远程并发操作,通过使用子进程而非线程有效地绕过了 全局解释器锁。因此,multiprocessing 模块允许程序员充分利用给定机器上的多个处理器。

其中使用了multiprocess这些库,我们可以调用它内部的函数terminate帮我们释放。例如t.terminate(),这样就可以强制让子进程退出了。

不过使用了多进程数据的交互方式比较繁琐,得使用共享内存、pipe或者消息队列这些进行子进程和父进程的数据交互。

示例代码如下:

import time
import gc
import datetime
import multiprocessing

def circle():
    print("begin")
    try:
        while True:
            current_time = datetime.datetime.now()
            print(str(current_time) + ' circle.................')
            time.sleep(3)
    except Exception as e:
        print('error:',e)
    finally:
        print('end')


if __name__ == "__main__":
    t = multiprocessing.Process(target=circle, args=())
    t.start()
    # Terminate the process
    current_time = datetime.datetime.now()
    print(str(current_time) + ' stoped before'
    time.sleep(1)
    t.terminate()  # sends a SIGTERM
    current_time = datetime.datetime.now()
    print(str(current_time) + ' stoped after'
    gc.collect()
    while True:
        time.sleep(3)
        current_time = datetime.datetime.now()
        print(str(current_time) + ' end circle'

多协程

协程(coroutine)也叫微线程,是实现多任务的另一种方式,是比线程更小的执行单元,一般运行在单进程和单线程上。因为它自带CPU的上下文,它可以通过简单的事件循环切换任务,比进程和线程的切换效率更高,这是因为进程和线程的切换由操作系统进行。

Python实现协程的主要借助于两个库:asyncioasyncio 是从Python3.4引入的标准库,直接内置了对协程异步IO的支持。asyncio 的编程模型本质是一个消息循环,我们一般先定义一个协程函数(或任务), 从 asyncio 模块中获取事件循环loop,然后把需要执行的协程任务(或任务列表)扔到 loop中执行,就实现了异步IO)和geventGevent 是一个第三方库,可以轻松通过gevent实现并发同步或异步编程,在gevent中用到的主要模式是Greenlet, 它是以C扩展模块形式接入Python的轻量级协程。)。

由于asyncio已经成为python的标准库了无需pip安装即可使用,这意味着asyncio作为Python原生的协程实现方式会更加流行。本文仅会介绍asyncio模块的退出使用。

使用协程取消,有两个重要部分:第一,替换旧的休眠函数为多协程的休眠函数;第二取消使用cancel()函数。

其中cancel() 返回值为 True 表示 cancel 成功。

示例代码如下:创建一个coroutine,然后调用run_until_complete()来初始化并启动服务器来调用main函数,判断协程是否执行完成,因为设置的num协程是一个死循环,所以一直没有执行完,如果没有执行完直接使用 cancel()取消掉该协程,最后执行成功。

import asyncio
import time


async def num(n):
    try:
        i = 0
        while True:
            print(f'i={i} Hello')
            i=i+1
            # time.sleep(10)
            await asyncio.sleep(n*0.1)
        return n
    except asyncio.CancelledError:
        print(f"数字{n}被取消")
        raise


async def main():
    # tasks = [num(i) for i in range(10)]
    tasks = [num(10)]
    complete, pending = await asyncio.wait(tasks, timeout=0.5)
    for i in complete:
        print("当前数字",i.result())
    if pending:
        print("取消未完成的任务")
        for p in pending:
            p.cancel()


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    try:
        loop.run_until_complete(main())
    finally:
        loop.close()

结语

这就是我自己的一些python 强制关闭线程、协程、进程的使用分享。如果大家有更好的想法和需求,也欢迎大家加我好友交流分享哈。

参考文章:

在思考如何强制关掉一个子线程或者子进程亦或者协程时候看了好多文章,python相关的很多信息,方便大家更细节的查看,我把链接放置在下方:

  • https://zhuanlan.zhihu.com/p/101199579
  • https://blog.csdn.net/waple_0820/article/details/93026922
  • https://zhuanlan.zhihu.com/p/68043798
  • https://blog.csdn.net/u012063703/article/details/51601579
  • http://tylderen.github.io/linux-multi-thread-signal
  • https://codeantenna.com/a/qtHjqJ7TWx
  • https://blog.csdn.net/HighDS/article/details/103867368
  • https://blog.51cto.com/u_13918080/3069098
  • https://blog.css8.cn/post/18797088.html

作者:良知犹存,白天努力工作,晚上原创公号号主。公众号内容除了技术还有些人生感悟,一个认真输出内容的职场老司机,也是一个技术之外丰富生活的人,摄影、音乐 and 篮球。关注我,与我一起同行。

                              ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧  END  ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧

推荐阅读

【1】jetson nano开发使用的基础详细分享

【2】Linux开发coredump文件分析实战分享

【3】CPU中的程序是怎么运行起来的 必读

【4】cartographer环境建立以及建图测试

【5】设计模式之简单工厂模式、工厂模式、抽象工厂模式的对比

本公众号全部原创干货已整理成一个目录,回复[ 资源 ]即可获得。


羽林君 某嵌入式程序猿分享技术、生活、人生云云文字。如有诗云:去年今日此门中,人面桃花相映红。人面不知何处去,桃花依旧笑春风。
评论 (0)
  • 浪潮之上:智能时代的觉醒    近日参加了一场课题的答辩,这是医疗人工智能揭榜挂帅的国家项目的地区考场,参与者众多,围绕着医疗健康的主题,八仙过海各显神通,百花齐放。   中国大地正在发生着激动人心的场景:深圳前海深港人工智能算力中心高速运转的液冷服务器,武汉马路上自动驾驶出租车穿行的智慧道路,机器人参与北京的马拉松竞赛。从中央到地方,人工智能相关政策和消息如雨后春笋般不断出台,数字中国的建设图景正在智能浪潮中徐徐展开,战略布局如同围棋
    广州铁金刚 2025-04-30 15:24 89浏览
  • 晶振在使用过程中可能会受到污染,导致性能下降。可是污染物是怎么进入晶振内部的?如何检测晶振内部污染物?我可不可以使用超声波清洗?今天KOAN凯擎小妹将逐一解答。1. 污染物来源a. 制造过程:生产环境不洁净或封装密封不严,可能导致灰尘和杂质进入晶振。b. 使用环境:高湿度、温度变化、化学物质和机械应力可能导致污染物渗入。c. 储存不当:不良的储存环境和不合适的包装材料可能引发化学物质迁移。建议储存湿度维持相对湿度在30%至75%的范围内,有助于避免湿度对晶振的不利影响。避免雨淋或阳光直射。d.
    koan-xtal 2025-04-28 06:11 123浏览
  •  探针台的维护直接影响其测试精度与使用寿命,需结合日常清洁、环境控制、定期校准等多维度操作,具体方法如下:一、日常清洁与保养1.‌表面清洁‌l 使用无尘布或软布擦拭探针台表面,避免残留清洁剂或硬物划伤精密部件。l 探针头清洁需用非腐蚀性溶剂(如异丙醇)擦拭,检查是否弯曲或损坏。2.‌光部件维护‌l 镜头、观察窗等光学部件用镜头纸蘸取wu水jiu精从中心向外轻擦,操作时远离火源并保持通风。3.‌内部防尘‌l 使用后及时吹扫灰尘,防止污染物进入机械滑
    锦正茂科技 2025-04-28 11:45 94浏览
  • 随着电子元器件的快速发展,导致各种常见的贴片电阻元器件也越来越小,给我们分辨也就变得越来越难,下面就由smt贴片加工厂_安徽英特丽就来告诉大家如何分辨的SMT贴片元器件。先来看看贴片电感和贴片电容的区分:(1)看颜色(黑色)——一般黑色都是贴片电感。贴片电容只有勇于精密设备中的贴片钽电容才是黑色的,其他普通贴片电容基本都不是黑色的。(2)看型号标码——贴片电感以L开头,贴片电容以C开头。从外形是圆形初步判断应为电感,测量两端电阻为零点几欧,则为电感。(3)检测——贴片电感一般阻值小,更没有“充放
    贴片加工小安 2025-04-29 14:59 126浏览
  • 一、智能家居的痛点与创新机遇随着城市化进程加速,现代家庭正面临两大核心挑战:情感陪伴缺失:超60%的双职工家庭存在“亲子陪伴真空期”,儿童独自居家场景增加;操作复杂度攀升:智能设备功能迭代导致用户学习成本陡增,超40%用户因操作困难放弃高阶功能。而WTR096-16S录音语音芯片方案,通过“语音交互+智能录音”双核驱动,不仅解决设备易用性问题,更构建起家庭成员间的全天候情感纽带。二、WTR096-16S方案的核心技术突破1. 高保真语音交互系统动态情绪语音库:支持8种语气模板(温柔提醒/紧急告警
    广州唯创电子 2025-04-28 09:24 179浏览
  • 在智能硬件设备趋向微型化的背景下,语音芯片方案厂商针对小体积设备开发了多款超小型语音芯片方案,其中WTV系列和WT2003H系列凭借其QFN封装设计、高性能与高集成度,成为微型设备语音方案的理想选择。以下从封装特性、功能优势及典型应用场景三个方面进行详细介绍。一、超小体积封装:QFN技术的核心优势WTV系列与WT2003H系列均提供QFN封装(如QFN32,尺寸为4×4mm),这种封装形式具有以下特点:体积紧凑:QFN封装通过减少引脚间距和优化内部结构,显著缩小芯片体积,适用于智能门铃、穿戴设备
    广州唯创电子 2025-04-30 09:02 120浏览
  • 贞光科技代理品牌紫光国芯的车规级LPDDR4内存正成为智能驾驶舱的核心选择。在汽车电子国产化浪潮中,其产品以宽温域稳定工作能力、优异电磁兼容性和超长使用寿命赢得市场认可。紫光国芯不仅确保供应链安全可控,还提供专业本地技术支持。面向未来,紫光国芯正研发LPDDR5车规级产品,将以更高带宽、更低功耗支持汽车智能化发展。随着智能网联汽车的迅猛发展,智能驾驶舱作为人机交互的核心载体,对处理器和存储器的性能与可靠性提出了更高要求。在汽车电子国产化浪潮中,贞光科技代理品牌紫光国芯的车规级LPDDR4内存凭借
    贞光科技 2025-04-28 16:52 171浏览
  • 文/Leon编辑/cc孙聪颖‍2023年,厨电行业在相对平稳的市场环境中迎来温和复苏,看似为行业增长积蓄势能。带着对市场向好的预期,2024 年初,老板电器副董事长兼总经理任富佳为企业定下双位数增长目标。然而现实与预期相悖,过去一年,这家老牌厨电企业不仅未能达成业绩目标,曾提出的“三年再造一个老板电器”愿景,也因市场下行压力面临落空风险。作为“企二代”管理者,任富佳在掌舵企业穿越市场周期的过程中,正面临着前所未有的挑战。4月29日,老板电器(002508.SZ)发布了2024年年度报告及2025
    华尔街科技眼 2025-04-30 12:40 104浏览
  • 网约车,真的“饱和”了?近日,网约车市场的 “饱和” 话题再度引发热议。多地陆续发布网约车风险预警,提醒从业者谨慎入局,这背后究竟隐藏着怎样的市场现状呢?从数据来看,网约车市场的“过剩”现象已愈发明显。以东莞为例,截至2024年12月底,全市网约车数量超过5.77万辆,考取网约车驾驶员证的人数更是超过13.48万人。随着司机数量的不断攀升,订单量却未能同步增长,导致单车日均接单量和营收双双下降。2024年下半年,东莞网约出租车单车日均订单量约10.5单,而单车日均营收也不容乐
    用户1742991715177 2025-04-29 18:28 139浏览
  • 4月22日下午,备受瞩目的飞凌嵌入式「2025嵌入式及边缘AI技术论坛」在深圳深铁皇冠假日酒店盛大举行,此次活动邀请到了200余位嵌入式技术领域的技术专家、企业代表和工程师用户,共享嵌入式及边缘AI技术的盛宴!1、精彩纷呈的展区产品及方案展区是本场活动的第一场重头戏,从硬件产品到软件系统,从企业级应用到高校教学应用,都吸引了现场来宾的驻足观看和交流讨论。全产品矩阵展区展示了飞凌嵌入式丰富的产品线,从嵌入式板卡到工控机,从进口芯片平台到全国产平台,无不体现出飞凌嵌入式在嵌入式主控设备研发设计方面的
    飞凌嵌入式 2025-04-28 14:43 124浏览
  • 文/郭楚妤编辑/cc孙聪颖‍越来越多的企业开始蚕食动力电池市场,行业“去宁王化”态势逐渐明显。随着这种趋势的加强,打开新的市场对于宁德时代而言至关重要。“我们不希望被定义为电池的制造者,而是希望把自己称作新能源产业的开拓者。”4月21日,在宁德时代举行的“超级科技日”发布会上,宁德时代掌门人曾毓群如是说。随着宁德时代核心新品骁遥双核电池的发布,其搭载的“电电增程”技术也走进业界视野。除此之外,经过近3年试水,宁德时代在换电业务上重资加码。曾毓群认为换电是一个重资产、高投入、长周期的产业,涉及的利
    华尔街科技眼 2025-04-28 21:55 84浏览
  • 一、gao效冷却与控温机制‌1、‌冷媒流动设计‌采用低压液氮(或液氦)通过毛细管路导入蒸发器,蒸汽喷射至样品腔实现快速冷却,冷却效率高(室温至80K约20分钟,至4.2K约30分钟)。通过控温仪动态调节蒸发器加热功率,结合温度传感器(如PT100铂电阻或Cernox磁场不敏感传感器),实现±0.01K的高精度温度稳定性。2、‌宽温区覆盖与扩展性‌标准温区为80K-325K,通过降压选件可将下限延伸至65K(液氮模式)或4K(液氦模式)。可选配475K高温模块,满足材料在ji端温度下的性能测试需求
    锦正茂科技 2025-04-30 13:08 93浏览
  • 你是不是也有在公共场合被偷看手机或笔电的经验呢?科技时代下,不少现代人的各式机密数据都在手机、平板或是笔电等可携式的3C产品上处理,若是经常性地需要在公共场合使用,不管是工作上的机密文件,或是重要的个人信息等,民众都有防窃防盗意识,为了避免他人窥探内容,都会选择使用「防窥保护贴片」,以防止数据外泄。现今市面上「防窥保护贴」、「防窥片」、「屏幕防窥膜」等产品就是这种目的下产物 (以下简称防窥片)!防窥片功能与常见问题解析首先,防窥片最主要的功能就是用来防止他人窥视屏幕上的隐私信息,它是利用百叶窗的
    百佳泰测试实验室 2025-04-30 13:28 96浏览
  • 在CAN总线分析软件领域,当CANoe不再是唯一选择时,虹科PCAN-Explorer 6软件成为了一个有竞争力的解决方案。在现代工业控制和汽车领域,CAN总线分析软件的重要性不言而喻。随着技术的进步和市场需求的多样化,单一的解决方案已无法满足所有用户的需求。正是在这样的背景下,虹科PCAN-Explorer 6软件以其独特的模块化设计和灵活的功能扩展,为CAN总线分析领域带来了新的选择和可能性。本文将深入探讨虹科PCAN-Explorer 6软件如何以其创新的模块化插件策略,提供定制化的功能选
    虹科汽车智能互联 2025-04-28 16:00 141浏览
我要评论
0
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦