1. 背景:
最近学习工作中时长需要跑上千或者上万条数,如果单线程跑万上万条数据耗费时间会比较长,所以想通过多线程并行跑完成
import requests
import os
from queue import Queue,LifoQueue,PriorityQueue
import threading
import time
class VideoModel:
def get_emotion(self,filename):
'''
调用接口,情绪模型接口
:param filename:一个音频文件wav或者ogg的
:return:情绪结果
'''
files = {'file': open(filename, 'rb')
}
headers = {'Content-Type': 'binary'}
url = 'http://xxxx'
try:
res = requests.post(url=url, files=files, headers=headers).json()
result = res['data']
except Exception as e:
print(e)
result = None
finally:
return result
def work(self,q):
'''
:param q: 传入一个队列
:return: 无
'''
while True:
if q.empty():
return
else:
filename=q.get()
result=self.get_asr(filename)
print(threading.currentThread().getName(),'--->',result)
def multithreading(self):
q=Queue()
filepath=r'E:\AI\******'
#将该目录下的文件放入队列q中
for files in os.listdir(filepath):
subfile=os.listdir(os.path.join(filepath,files))
for file in subfile:
q.put(os.path.join(filepath,files, file))
thread_num=10 #创建10个线程
threads=[]
for i in range(thread_num):
t=threading.Thread(target=self.work,args=(q,))
#args需要输出的是一个元组,如果只有一个参数,后面加,表示元组,否则会报错
threads.append(t)
for i in range(thread_num):
threads[i].start()
for i in range(thread_num):
threads[i].join()
print("线程执行完成-------------------------")
if __name__ == '__main__':
start=time.time()
vedio=VideoModel()
vedio.multithreading()
print('耗时:',time.time()-start)
- work(self,q):改方法主要用于每个线程从queue(生产者)中取数,并去调用get_emotion方法
- get_emotion():最小原子接口,需要并发的接口,相当于消费者。
- Multithreading(self):改方法主要用于构造多个线程
threading模块:
Python的多线程还是主要使用标准库threading,该库提供了更高级别、功能更全面的线程管理。
该模块提供的主要方法:
threading.currentThread(): 返回当前的线程变量。
threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
run(): 用以表示线程活动的方法。
start():启动线程活动。
join([time]): 等待至线程中止。这阻塞调用线程直至线程的join() 方法被调用中止-正常退出或者抛出未处理的异常-或者是可选的超时发生。
isAlive(): 返回线程是否活动的。
getName(): 返回线程名。
setName(): 设置线程名。
queue模块:
Queue的对象有:
Queue.Queue(maxsize=0):创建大小为maxsize的FIFO(First In First Out)-Queue对象,如果maxsize不设置,这个队列将是无限的。
Queue.LifoQueue(maxsize=0): 创建先入后出的对象,即栈。Queue.PriorityQueue(maxsize=0):有优先级的队列。
Queue对象的方法有:
queue对象实现一个fifo队列(其他的还有lifo、priority队列,这里不再介绍)。queue只有qsize一个构造参数,用来指定队列容量,指定为0的时候代表容量无限。主要有以下成员函数:
Queue.qsize():返回消息队列的当前空间。返回的值不一定可靠。
Queue.empty():判断消息队列是否为空,返回True或False。同样不可靠。
Queue.full():类似上边,判断消息队列是否满
Queue.put(item, block=True, timeout=None):往消息队列中存放消息。block可以控制是否阻塞,timeout指定阻塞时候的等待时间。如果不阻塞或者超市,会引起一个full exception。
Queue.put_nowait(item):相当于put(item, False).
Queue.get(block=True, timeout=None):获取一个消息,其他同put。
以下两个函数用来判断消息对应的任务是否完成。
Queue.task_done():接受消息的线程通过调用这个函数来说明消息对应的任务已完成。
Queue.join():调用线程阻塞直到所有消息对应的任务已经完成。
消息队列实例中维护的有待完成任务变量。每接收到一个消息该值自增一次。每调用一次.task_done()可以使该值减1,当待完成任务值为0的时候,join函数才会返回。