threading用于提供线程相关的操作,线程是应用程序中工作的最小单元。python当前版本的多线程库没有实现优先级、线程组,线程也不能被停止、暂停、恢复、中断。
threading模块提供的类:
Thread, Lock, Rlock, Condition, [Bounded]Semaphore, Event, Timer, local。
threading 模块提供的常用方法:
threading.currentThread(): 返回当前的线程变量。
threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
threading 模块提供的常量:
threading.TIMEOUT_MAX 设置threading全局超时时间。
好了,正文开始:
最近需要用python写一个环境搭建工具,多线程并行对环境各个部分执行一些操作,并最终知道这些并行执行的操作是否都执行成功了,也就是判断这些操作函数的返回值是否为0。但是threading并没有显式的提供获取各个线程函数返回值的方法,只好自己动手,下面就介绍一下自己的实现方式。
一开始考虑到执行的操作可能有很多,而且后续会不断补充,因此先写了一个通用的多线程执行类,封装线程操作的基本方法,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
import threading
class MyThread(object):
def __init__(self, func_list=None):
#所有线程函数的返回值汇总,如果最后为 0 ,说明全部成功
self.ret_flag = 0
self.func_list = func_list
self.threads = []
def set_thread_func_list(self, func_list):
"" "
@note : func_list是一个list,每个元素是一个dict,有func和args两个参数
"" "
self.func_list = func_list
def start(self):
"" "
@note : 启动多线程执行,并阻塞到结束
"" "
self.threads = []
self.ret_flag = 0
for func_dict in self.func_list:
if func_dict[ "args" ]:
t = threading.Thread(target=func_dict[ "func" ], args=func_dict[ "args" ])
else :
t = threading.Thread(target=func_dict[ "func" ])
self.threads.append(t)
for thread_obj in self.threads:
thread_obj.start()
for thread_obj in self.threads:
thread_obj.join()
def ret_value(self):
"" "
@note : 所有线程函数的返回值之和,如果为 0 那么表示所有函数执行成功
"" "
return self.ret_flag
|
MyThread类会接受一个func_list参数,每个元素是一个dict,有func和args两个key,func是真正要执行的函数引用,args是函数的参数。其中最主要的方法是start方法,会多线程执行每个func,然后一直等到所有线程都执行结束后退出。接下来的关键就是如何对self.ret_flag设置正确的值,以判断所有的线程函数是否都返回0了。
我的实现是,在MyThread class中写一个方法trace_func,作为直接的线程函数,这个trace_func中执行真正需要执行的函数,从而可以获取到该函数的返回值,设置给self.ret_flag。
这个trace_func的第一参数是要执行的func引用,后面是这个func的参数,具体代码如下:
1
2
3
4
5
6
|
def trace_func( self , func, * args, * * kwargs):
"""
@note:替代profile_func,新的跟踪线程返回值的函数,对真正执行的线程函数包一次函数,以获取返回值
"""
ret = func( * args, * * kwargs)
self .ret_flag + = ret
|
这样就需要修改start方法中Thread函数的设置,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
def start( self ):
"""
@note: 启动多线程执行,并阻塞到结束
"""
self .threads = []
self .ret_flag = 0
for func_dict in self .func_list:
if func_dict[ "args" ]:
new_arg_list = []
new_arg_list.append(func_dict[ "func" ])
for arg in func_dict[ "args" ]:
new_arg_list.append(arg)
new_arg_tuple = tuple (new_arg_list)
t = threading.Thread(target = self .trace_func, args = new_arg_tuple)
else :
t = threading.Thread(target = self .trace_func, args = (func_dict[ "func" ],))
self .threads.append(t)
for thread_obj in self .threads:
thread_obj.start()
for thread_obj in self .threads:
thread_obj.join()
|
这样能够成功获得返回值了,实验:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
def func1(ret_num):
print "func1 ret:%d" % ret_num
return ret_num
def func2(ret_num):
print "func2 ret:%d" % ret_num
return ret_num
def func3():
print "func3 ret:100"
return 100
mt = MyThread()
g_func_list = []
g_func_list.append({ "func" :func1, "args" :( 1 ,)})
g_func_list.append({ "func" :func2, "args" :( 2 ,)})
g_func_list.append({ "func" :func3, "args" : None })
mt.set_thread_func_list(g_func_list)
mt.start()
print "all thread ret : %d" % mt.ret_flag
|
最后的输出结果
1
2
3
4
|
func1 ret: 1
func2 ret: 2
func3 ret: 100
all thread ret : 103
|
总结
以上所述是小编给大家介绍的python使用threading获取线程函数返回值的实现方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对服务器之家网站的支持!
原文链接:https://www.cnblogs.com/qualitysong/archive/2011/05/27/2060246.html