将一些线程函数分组到Python中
我有一些函数,我希望它们位于不同的线程组中。也就是说,我想让这些不同的线程组依次运行。我的示例代码如下所示:将一些线程函数分组到Python中,python,multithreading,grouping,Python,Multithreading,Grouping,我有一些函数,我希望它们位于不同的线程组中。也就是说,我想让这些不同的线程组依次运行。我的示例代码如下所示: import threading from threading import Thread def func_a(): # do something here def func_b(): # do something here def func_c(): # do something here def func_d(): # do somethi
import threading
from threading import Thread
def func_a():
# do something here
def func_b():
# do something here
def func_c():
# do something here
def func_d():
# do something here
thread_a = threading.Thread(target = func_a)
thread_b = threading.Thread(target = func_b)
thread_c = threading.Thread(target = func_c)
thread_d = threading.Thread(target = func_d)
thread_a.start()
thread_b.start()
thread_c.start()
thread_d.start()
thread_a.join()
thread_b.join()
thread_c.join()
thread_d.join()
我想做的很简单:把a
func\u a
和func\u b
作为threading\u group\u a
,也把func\u c
和func\u d
作为threading\u group\u b
。然后先执行threading\u group\u a
,然后执行threading\u group\u b
您可以使用池。这是将线程分组并为其分配单个任务的方法。然后将任务分配给池,而不是特定的线程。您有4个函数,但它们只做2件事。因此,您可以这样做:
from multiprocessing.pool import ThreadPool
def func_a(*args):
print 1
def func_b(*args):
print 2
pool = ThreadPool(3)
pool.map(func_a, range(2))
pool.map(func_b, range(2))
11
22
注意,我必须更改函数签名,因为pool.map
将一些参数传递给函数。文档指定映射块,直到结果准备就绪,因此我们可以删除.join()
更新:是的,你可以。假设你需要a+b一起执行。您可以将它们封装在第三个函数中,它所做的只是调用其他两个函数:
def ab(*args):
func_a()
func_b()
现在将ab
函数传递给线程池。如果需要从函数返回值,则将返回值分配给列表并返回该列表
更新2:
from multiprocessing.pool import ThreadPool
def func_a():
print 1
def func_b():
print 2
def ab(*args):
func_a()
func_b()
pool = ThreadPool(3)
pool.map(ab, range(2))
有两个问题需要考虑:
线程分组
流量控制
您可以采用手动方式,使用list
s或tuple
s对参数和线程本身进行分组,还可以手动控制流:
from threading import Thread
# Functions for group 1: with no arguments and different fucntions
def func_a():
print(1)
def func_b():
print(1)
# Functions for group 2: with a single function but different arguments
def func_c(i):
print(i)
# Functions for group 3: with different functions and arguments
def func_d(i):
print(i)
def func_e(i):
print(i)
funs_1 = (func_a, func_b)
args_2 = ((2,), (2,))
funs_3 = (func_d, func_e)
args_3 = ((3,), (3,))
threads_1 = tuple(Thread(target=func ) for func in funs_1)
threads_2 = tuple(Thread(target=func_c, args=args) for args in args_2)
threads_3 = tuple(Thread(target=func, args=args) for func, args in zip(funs_3, args_3))
for thread in threads_1:
thread.start()
for thread in threads_1:
thread.join()
for thread in threads_2:
thread.start()
for thread in threads_2:
thread.join()
for thread in threads_3:
thread.start()
for thread in threads_3:
thread.join()
或者使用池,该池允许您指定可以启动的并发线程的数量,并且还将处理该控件:
from concurrent.futures import ThreadPoolExecutor
# Functions for group 1: with no arguments and different fucntions
def func_a():
print(1)
def func_b():
print(1)
# Functions for group 2: with a single function but different arguments
def func_c(i):
print(i)
# Functions for group 3: with different functions and arguments
def func_d(i):
print(i)
def func_e(i):
print(i)
funs_1 = (func_a, func_b)
args_2 = ((2,), (2,))
funs_3 = (func_d, func_e)
args_3 = ((3,), (3,))
with ThreadPoolExecutor(max_workers=5) as pool:
futures_1 = tuple(pool.submit(func) for func in funs_1)
with ThreadPoolExecutor(max_workers=5) as pool:
futures_2 = tuple(pool.submit(func_c, *args) for args in args_2)
with ThreadPoolExecutor(max_workers=5) as pool:
futures_3 = tuple(pool.submit(func, *args) for func, args in zip(funs_3, args_3))
with
语句确保池在退出之前完成所有任务。您只需要调用ThreadPoolExecutor
实例方法submit()
作为第一个参数,目标
关键字参数等价物以及其他位置参数和关键字参数将传递给函数,如线程
中的args
和kwargs
关键字参数concurrent.futures
位于Python3的标准库中,并且已经为Python2.5+移植,您可能需要在thread\u c.start()
和thread\u d.start()之前使用thread\u a.join()
和thread\u d.start()
执行sudo pip安装futures是否可以?或者你想要一种自动的方式来处理更多的线程?@RomanPerekhrest我不完全同意,有些情况下,你需要一些操作的结果才能处理其他操作。期货和池是解决这种情况的wya,在我看来,它们是一个非常合法的用例。@adrio,仅仅说期货和池是一个非常合法的用例是不够的,最好在实践中加以证明。你可以通过张贴适当的answer@RomanPerekhrest我正在发布答案。谢谢!但是我不太明白什么是args_1=((1,),(1,)
和args_2=((2,),(2,)
?这是否意味着我的函数的输出?如果是这样的话,情况是在执行之前我没有函数的输出。。。是否有其他方法将函数本身放入args
而不是输出?谢谢!!它们是传递给函数的参数。我将它们存储在元组中以便进行迭代,但您可以查看第二组ThreadPoolExecutor方法的示例,其中我不使用元组存储。为了简化,我希望将my函数本身放入线程
中的目标
。是的。。我看到了你的第二个,但它仍然没有把整个功能作为目标。此外,我更愿意为此使用线程化模块。谢谢是的,我就是这么做的。我正在使用打印
作为功能,您可以用您为功能指定的任何名称替换它。例如,如果您不需要传递任何参数,您可以为future\u 21=pool.submit(my\u func)
替换future\u 21=pool.submit(my\u func,arg1,arg2,kwarg1=value1,kwarg2=value2)
。。。有没有办法把我所有的功能都放进去?请注意,我的示例代码只是示例。我想做的是按顺序在不同的线程组中执行几个函数。@ryan9025您可以使用包装器函数来执行。我已经更新了我的答案谢谢!因此,我创建了一个变量pool=ThreadPool(ab)
。但是pool.map
部分呢?@ryan9025不,您应该创建一个池,并在池中传递所需的线程数。pool.map
是将工作分配给线程的部分。所以,pool=ThreadPool(4)
然后pool.map(func,range(num\u of\u迭代))
。阅读文档中有关pool
的更多信息好的,但现在它重新运行TypeError:“ThreadPool”对象不可调用
?