Python 自定义线程池,上下文管理with
python 中只为我们定了进程池,没有实现进程池,需要我们自己实现
1.简单版的线程池,通过队列来实现
import threading import time import queue #简单版的线程池 class ThreadPool(object): def __init__(self,maxsize=10): self.queue = queue.Queue(maxsize) for i in range(maxsize): self.queue.put(threading.Thread) #放入的是线程类名 #获取线程 def get_thread(self): return self.queue.get() #放入线程 def put_thread(self): self.queue.put(threading.Thread) def func(args,pool): time.sleep(1) print(args) pool.put_thread() #放入线程 threadpool = ThreadPool(15) #创建一个15个的线程池 for i in range(100): thread = threadpool.get_thread() #获取线程 th = thread(target=func,args=(i,threadpool,)) th.start()
2.高级版线程池
#!/usr/bin/env python # -*- coding:utf-8 -*- import queue import threading import contextlib import time StopEvent = object() #停止标志符 class ThreadPool(object): def __init__(self, max_num, max_task_num = None): if max_task_num: #定义队列中最大任务数 self.q = queue.Queue(max_task_num) else: self.q = queue.Queue() self.max_num = max_num #最大线程数 self.cancel = False self.terminal = False self.generate_list = [] #定义产生线程列表 self.free_list = [] #定义空闲线程列表 def run(self, func, args, callback=None): """ 线程池执行一个任务 :param func: 任务函数 :param args: 任务函数所需参数 :param callback: 任务执行失败或成功后执行的回调函数,回调函数有两个参数1、任务函数执行状态;2、任务函数返回值(默认为None,即:不执行回调函数) :return: 如果线程池已经终止,则返回True否则None """ if self.cancel: return #如果空闲数为0 并且产生的线程数小于最大的线程数 if len(self.free_list) == 0 and len(self.generate_list) < self.max_num: self.generate_thread() #产生线程 w = (func, args, callback,) #封装任务元组(函数,参数,回调函数) self.q.put(w) #队列中添加任务 def generate_thread(self): """ 创建一个线程 """ t = threading.Thread(target=self.call) t.start() def call(self): """ 循环去获取任务函数并执行任务函数 """ #获取执行当前函数的线程 current_thread = threading.currentThread() #将当前线程添加到产生的线程列表 self.generate_list.append(current_thread) #获取队列中的任务 event = self.q.get() while event != StopEvent: #如果任务不等于停止标志 #任务解包 func, arguments, callback = event try: result = func(*arguments) # 执行任务 success = True except Exception as e: success = False #执行任务失败 result = None if callback is not None: #回调函数不为空 try: callback(success, result) #执行回调函数 except Exception as e: pass #执行回调函数失败什么都不做 with self.worker_state(self.free_list, current_thread): if self.terminal: # 默认为false ,如果terminal == True event = StopEvent # 将event设置为StopEvent,终止循环 else: event = self.q.get() # 从队列取任务 else: #任务等于停止标志 在产生的线程中移除当前线程 self.generate_list.remove(current_thread) def close(self): """ 执行完所有的任务后,所有线程停止 """ self.cancel = True full_size = len(self.generate_list) #产生了多少个线程,在结束的时候,就要添加多少个停止标志符 while full_size: self.q.put(StopEvent) #将停止符加入队列 full_size -= 1 def terminate(self): """ 无论是否还有任务,终止线程 """ self.terminal = True while self.generate_list: #如果产生的线程列表还有线程 self.q.put(StopEvent) #向队列添加终止符 self.q.queue.clear() #清空队列 @contextlib.contextmanager def worker_state(self, state_list, worker_thread): """ 用于记录线程中正在等待的线程数 """ state_list.append(worker_thread) try: yield finally: state_list.remove(worker_thread) # How to use pool = ThreadPool(5) def callback(status, result): # status, execute action status # result, execute action return value pass def action(i): print(i) for i in range(30): ret = pool.run(action, (i,), callback) time.sleep(5) print(len(pool.generate_list), len(pool.free_list)) print(len(pool.generate_list), len(pool.free_list)) pool.close() # pool.terminate()
3.上下文管理with
import contextlib @contextlib.contextmanager def test(): print('first') # 2 try: yield # 3 finally: print('third') #5 with test(): # 1 print('second') # 4
自定义open函数
import contextlib @contextlib.contextmanager def myopen(file_path,mode): f1 = open(file_path,mode) try: yield f1 finally: f1.close() with myopen('1.txt','r') as f: print(f.read())

浙公网安备 33010602011771号