从接触python开始,就不断地听见有人说,为了提高效率,要使用多线程,为了某某,要使用多线程,可是自己的工作中数据不是很大,对于多线程的需求不是很高,基本都是顺序执行,但就在不久前,处理的数据有点多,而且有n多个表,处理的时间长不长不说,就是都进来都得10分钟,甚至更久,没办法,只能找找多线程的使用方法了!
关于各种线程、进程的,我不再扯,因为我也不是很懂,直接上简单的例子,以及我工作中使用的代码及思想
def run(n):
print('task',n)
time.sleep(1)
print('2s')
time.sleep(1)
print('1s')
time.sleep(1)
print('0s')
time.sleep(1)
if __name__ == '__main__':
t1 = datetime.now()
run("t1")
run("t2")
t2 = datetime.now()
print(t2-t1)
out:
task t1
2s
1s
0s
task t2
2s
1s
0s
0:00:08.001793
-----------------------------------------------------------------------
import time
import threading
def run(n):
print('task',n)
time.sleep(1)
print('2s')
time.sleep(1)
print('1s')
time.sleep(1)
print('0s')
time.sleep(1)
if __name__ == '__main__':
t1 = datetime.now()
th1 = threading.Thread(target=run,args=('t1',)) # target是要执行的函数名(不是函数),args是函数对应的参数,以元组的形式存在
th2 = threading.Thread(target=run,args=('t2',))
th1.start()
th2.start()
th1.join()
th2.join()
t2 = datetime.now()
print(t2-t1)
out:
task t1
task t2
2s
2s
1s
1s
0s
0s
0:00:04.007415
上面的例子,前一部分代码是没加线程,完全是顺序执行,第二部分是加了多线程,从执行的时间上来看,和预想的一样,顺序执行相当于执行了两次run函数;多线程两次一起开始,时间只是之前的一半。
至于第二部分代码中使用的join方法,该方法作用在于使得主线程等待子线程结束后才结束,不然主线程比子线程快,之后主线程调用子线程的结果没法调用。我注释掉,看看效果。
def run(n):
print('task',n)
time.sleep(1)
print('2s')
time.sleep(1)
print('1s')
time.sleep(1)
print('0s')
time.sleep(1)
if __name__ == '__main__':
t1 = datetime.now()
th1 = threading.Thread(target=run,args=('t1',)) # target是要执行的函数名(不是函数),args是函数对应的参数,以元组的形式存在
th2 = threading.Thread(target=run,args=('t2',))
th1.start()
th2.start()
# th1.join()
# th2.join()
t2 = datetime.now()
print(t2-t1)
"""
可以看到,先执行的是主线程的print(t2-t1),后执行子线程,若主线程要用到子线程的结果,
那么肯定会报错
"""
out:
task t1
task t2
0:00:00.004987
2s
2s
1s
1s
0s
0s
至于多线程介绍,可以看看这个大神的,很细很全面,给大神多点赞!🙈🙈🙈
现在开始我面临的问题以及处理方法
首先我的问题是处理数据之前需要把数据加载进来,数据分两个文件夹,每个文件夹又有很多文件,顺序执行的话需要12分钟左右,实在等的焦急,所以考虑使用多线程同时开始读取两个文件夹的数据(当然你还想快可以把每个文件夹分成几部分,多建几个线程读取,最后把数据合起来),预想两个文件夹文件个数、大小差不多,节省一般时间,完全满足要求,没再细分。
增加线程的代码如下:
"""
load_total_publish_data:
load_total_all_orders:
上面两个分别是我构建的读取数据的函数
"""
t1 = MyThread(load_total_publish_data, args=(publish_data_path_list, all_account_mapping))
t2 = MyThread(load_total_all_orders, args=(all_orders_path_list,))
t1.start()
t1.join()
t2.start()
t2.join()
total_publish_data_temp = t1.get_result()[0]#这里切片是因为函数返回值有两个
Current_month_publish_data_temp = t1.get_result()[1]
total_all_orders = t2.get_result()[0]
Current_month_all_orders = t2.get_result()[1]
"""
上面代码需要解释的是:因为我还需要处理读取进来的数据,所以需要用到两个进程的返回值,为了获取返回值,
重写Thread类,具体代码如下,然后使用.get_result()方法获取返回值
"""
class MyThread(threading.Thread):
def __init__(self,func,args=()):
super(MyThread,self).__init__()
self.func = func
self.args = args
def run(self):
self.result = self.func(*self.args)
def get_result(self):
try:
return self.result
except Exception:
return None
搞完之后开始测试代码,之前的代码跑完需要12分钟多,而建了多线程的只需要五分钟,就很Nice!!
🙈🙈🙈🙈🙈🙈🙈🙈
🙈🙈🙈🙈🙈🙈🙈
希望对有缘人有帮助,也是给我一个记笔记的机会,免得下次不会用!