由于项目要多次向接口发送请求获取数据,为了提高运行效率,研究了一下Python的线程和进程。两者运用于I/O密集型任务,但是线程运行效率高,共享内存,可以同时修改数据,缺点是受到Python语言自带的Global Interpreter Lock (GIL)限制;同时为了满足优点,还需要辅助工具比如锁,队列这样就很复杂,耗资源。进程内存独立,代码独立,能够充分利用GPU和内核,缺点是进程间无法交流,无法共享数据,耗内存。
回到我的项目,我的做法就是给每个请求开一个线程
线程
线程运行,并且获取线程返回结果
import threading
class MyThread(threading.Thread):
def __init__(self,func,delay=2, args=()):
"""
:param func: 线程函数
:param args: 传递给线程函数的参数,他必须是个tuple类型
"""
threading.Thread.__init__(self)
self.func = func
self.args = args
self.delay = delay
def run(self):
time.sleep(self.delay)
self.result = self.func(self.args)
def get_result(self):
threading.Thread.join(self)
print("退出进程 %s"%self.delay)
try:
return self.result
except Exception as err:
logger.info("get result error %s"%err)
return None
def run_thread(func,*args, count=10):
"""
线程实例化,运行线程过程
:param func: 线程函数
:param args: 线程函数的参数
:param count: 线程个数
:return: 线程结果组成的list
"""
threads = []
result = []
while count > 0:
thread = MyThread(func,*args, count)
thread.start()
threads.append(thread)
count -= 1
for thread in threads:
t = thread.get_result()
result.append(t)
print("退出主线程")
return result
线程池ThreadPool
mutiproccessing.dummy就是一个套了mutiproccessing(多进程)API的线程
如下采用的是异步apply_async方法,每次10个线程运行。线程池的优点:避免线程的创建和销毁带来的性能开销,避免大量的线程间因互相抢占系统资源导致的阻塞现象
from multiprocessing.dummy import Pool as ThreadPool
datalist = []
async_pool = ThreadPool(processes=10) #线程数=10
results={}
try:
for ele in data:
uuid = ele.get('uuid')
result = async_pool.apply_async(get_info_by_uuid, (uuid,)) #线程池
results[uuid] = result
for k in results:
results[k].wait() # 等待线程函数执行完毕
for k in results:
value = results[k]
if value.ready(): # 线程函数是否已经启动了
if value.successful(): # 线程函数是否执行成功
item = value.get() # 线程函数返回值
_item = item.copy()
_item['uuid'] = k
datalist.append(_item)
return datalist
except Exception:
raise