python怎么比较优雅地停止线程

一直以来如何停止python线程是件比较麻烦的事情, 因为很多操作需要放到线程中去做, 而有时候又需要即时关闭线程, 比如对于硬件串口的读取。

在之前停止线程有几种方式, 要么在内部的循环里加信号监听, 或者开子进程, 调用进程的停止方法去停止专门为了线程开的进程, 但是前者如果逻辑比较复杂, 循环中各部分可能都有不同的逻辑再跑, 可能信号监听会有错漏, 而后者, 进程本身就是一种资源消耗, 在开发板中, 多开几个进程, 也就资源耗尽了。

这次在网上搜罗了一番, 找到了ctypes里面的pythonapi中, 有个PyTrheadState_SetAsyncExc的东西, 貌似可以修改线程的状态, 尝试了下, 确实可是, 那么加以封装, 基本上就可以在原有threading.Thread上面封装出来一个带stop的线程类。

同时附加一个blinker的信号通知, 可以在子线程中触发调用主线程中方法, 这样可以更方便的使用异步方式解耦主子线程中的逻辑。

import ctypes
import inspect
import threading
import time

from blinker import signal

s = signal('king')

def animal(*args, **kwargs):
    print(args)
    if args[0] == 10:
        print('exit')
        t.stop()

def async_print():
    for i in range(1000):
        s.send(i)
        time.sleep(1)

s.connect(animal)

class MyThread(threading.Thread):

    def stop(self):
        try:
            self._async_raise(self.ident, SystemExit)
        except Exception as e:
            print(str(e))

    def _async_raise(self, tid, exctype):
        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 Exception('invalid thread id')
        elif res != 1:
            ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
            raise SystemError("PyThreadState_SetAsyncExc failed")

if __name__ == '__main__':
    t = MyThread(target=async_print)
    t.start()
    t.join()

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值