python子线程退出及线程退出控制的代码

yipeiwu_com6年前Python基础

下面通过代码给大家介绍python子线程退出问题,具体内容如下所示:

def thread_func():
  while True:
      #do something
      #do something
      #do something
t=threading.Thread(target = thread_func)
t.start()
# main thread do something
# main thread do something
# main thread do something

跑起来是没有问题的,但是使用ctrl + c中断的时候出问题了,主线程退出了,但子线程仍然运行。

于是在主线程增加了信号处理的代码,收到sigint时改变子线程循环条件

loop = True
def thread_func():
  while loop:
      #do something
      #do something
      #do something
t=threading.Thread(target = thread_func)
t.start()
# ctrl+c时,改变loop为False
def handler(signum, frame):
  global loop
  loop = False
  t.join()
  exit(0)
signal(SIGINT, handler)
# main thread do something
# main thread do something
# main thread do something

这样ctrl+c就可以退出了,但是疑惑的是,主线程退出进程不会退出吗?

知识点扩展Python线程退出控制

ctypes模块控制线程退出

Python中threading模块并没有设计线程退出的机制,原因是不正常的线程退出可能会引发意想不到的后果。

例如:

线程正在持有一个必须正确释放的关键资源,锁。

线程创建的子线程,同时也将被杀掉。

管理自己的线程,最好的处理方式是拥有一个请求退出标志,这样每个线程依据一定的时间间隔检查规则,看是不是需要退出。

例如下面的代码:

import threading
class StoppableThread(threading.Thread):
  """Thread class with a stop() method. The thread itself has to check
  regularly for the stopped() condition."""

  def __init__(self):
    super(StoppableThread, self).__init__()
    self._stop_event = threading.Event()

  def stop(self):
    self._stop_event.set()

  def stopped(self):
    return self._stop_event.is_set()

这段代码里面,线程应该定期检查停止标志,在退出的时候,可以调用stop()函数,并且使用join()函数来等待线程的退出。

然而,可能会出现确实想要杀掉线程的情况,例如你正在封装一个外部库,它会忙于长时间调用,而你想中断它。

Python线程可以抛出异常来结束:

传参分别是线程id号和退出标识

def _async_raise(tid, exctype):
  '''Raises an exception in the threads with id tid'''
  if not inspect.isclass(exctype):
    raise TypeError("Only types can be raised (not instances)")
  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, 0)
    raise SystemError("PyThreadState_SetAsyncExc failed")

如果线程在python解释器外运行时,它将不会捕获中断,即抛出异常后,不能对线程进行中断。

简化后,以上代码可以应用在实际使用中来进行线程中断,例如检测到线程运行时常超过本身可以忍受的范围。

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)

总结

以上所述是小编给大家介绍的python子线程退出及线程退出控制的代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对【听图阁-专注于Python设计】网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

相关文章

Python中关于浮点数的冷知识

本周的PyCoder's Weekly 上分享了一篇小文章,它里面提到的冷知识很有意思,我稍作补充,分享给大家。 它提到的部分问题,读者们可以先思考下: 若两个元组相等,即 a==...

Python中使用logging和traceback模块记录日志和跟踪异常

Python中使用logging和traceback模块记录日志和跟踪异常

logging模块 logging模块用于输出运行日志,可以设置不同的日志等级,保存信息到日志文件中等。 相比print,logging可以设置日志的等级,控制在发布版本中的输出内容,并...

Python针对给定字符串求解所有子序列是否为回文序列的方法

Python针对给定字符串求解所有子序列是否为回文序列的方法

本文实例讲述了Python针对给定字符串求解所有子序列是否为回文序列的方法。分享给大家供大家参考,具体如下: 问题: 给定一个字符串,得到所有的子序列,判断是否为回文序列 思路: 对字符...

python模块之paramiko实例代码

本文研究的主要是python模块之paramiko的相关用法,具体实现代码如下,一起来看看。 paramiko模块提供了ssh及sft进行远程登录服务器执行命令和上传下载文件的功能。这是...

Python的lambda匿名函数的简单介绍

lambda函数也叫匿名函数,即,函数没有具体的名称。先来看一个最简单例子:复制代码 代码如下:def f(x):return x**2print f(4)Python中使用lambda...