下面的函数foo
返回一个字符串'foo'
。如何获取从线程目标返回的值'foo'
?
from threading import Thread
def foo(bar):
print('hello {}'.format(bar))
return 'foo'
thread = Thread(target=foo, args=('world!',))
thread.start()
return_value = thread.join()
上面显示的“一种显而易见的方法”不起作用:thread.join()
返回None
。
答案 0 :(得分:235)
FWIW,multiprocessing
模块使用Pool
类有一个很好的接口。如果你想坚持使用线程而不是进程,你可以使用multiprocessing.pool.ThreadPool
类作为替换。
def foo(bar, baz):
print 'hello {0}'.format(bar)
return 'foo' + baz
from multiprocessing.pool import ThreadPool
pool = ThreadPool(processes=1)
async_result = pool.apply_async(foo, ('world', 'foo')) # tuple of args for foo
# do some other stuff in the main process
return_val = async_result.get() # get the return value from your function.
答案 1 :(得分:189)
我看到的一种方法是将一个可变对象(如列表或字典)传递给线程的构造函数,以及某种索引或其他标识符。然后,线程可以将其结果存储在该对象的专用槽中。例如:
def foo(bar, result, index):
print 'hello {0}'.format(bar)
result[index] = "foo"
from threading import Thread
threads = [None] * 10
results = [None] * 10
for i in range(len(threads)):
threads[i] = Thread(target=foo, args=('world!', results, i))
threads[i].start()
# do some other stuff
for i in range(len(threads)):
threads[i].join()
print " ".join(results) # what sound does a metasyntactic locomotive make?
如果您真的希望join()
返回被调用函数的返回值,可以使用Thread
子类执行此操作,如下所示:
from threading import Thread
def foo(bar):
print 'hello {0}'.format(bar)
return "foo"
class ThreadWithReturnValue(Thread):
def __init__(self, group=None, target=None, name=None,
args=(), kwargs={}, Verbose=None):
Thread.__init__(self, group, target, name, args, kwargs, Verbose)
self._return = None
def run(self):
if self._Thread__target is not None:
self._return = self._Thread__target(*self._Thread__args,
**self._Thread__kwargs)
def join(self):
Thread.join(self)
return self._return
twrv = ThreadWithReturnValue(target=foo, args=('world!',))
twrv.start()
print twrv.join() # prints foo
由于某些名称错误导致它变得有点毛茸茸,并且它访问特定于Thread
实现的“私有”数据结构......但它可以工作。
对于python3
class ThreadWithReturnValue(Thread):
def __init__(self, group=None, target=None, name=None,
args=(), kwargs={}, Verbose=None):
Thread.__init__(self, group, target, name, args, kwargs)
self._return = None
def run(self):
print(type(self._target))
if self._target is not None:
self._return = self._target(*self._args,
**self._kwargs)
def join(self, *args):
Thread.join(self, *args)
return self._return
答案 2 :(得分:73)
Jake的答案很好,但是如果你不想使用线程池(你不知道你需要多少线程,但是根据需要创建它们)那么在线程之间传输信息的好方法是内置Queue.Queue类,因为它提供了线程安全性。
我创建了以下装饰器,使其以类似于threadpool的方式运行:
def threaded(f, daemon=False):
import Queue
def wrapped_f(q, *args, **kwargs):
'''this function calls the decorated function and puts the
result in a queue'''
ret = f(*args, **kwargs)
q.put(ret)
def wrap(*args, **kwargs):
'''this is the function returned from the decorator. It fires off
wrapped_f in a new thread and returns the thread object with
the result queue attached'''
q = Queue.Queue()
t = threading.Thread(target=wrapped_f, args=(q,)+args, kwargs=kwargs)
t.daemon = daemon
t.start()
t.result_queue = q
return t
return wrap
然后你只需将其用作:
@threaded
def long_task(x):
import time
x = x + 5
time.sleep(5)
return x
# does not block, returns Thread object
y = long_task(10)
print y
# this blocks, waiting for the result
result = y.result_queue.get()
print result
每次调用时,trim函数会创建一个新线程,并返回一个包含将接收结果的队列的Thread对象。
<强>更新强>
自从我发布这个答案以来已经有一段时间了,但它仍然可以获得视图,所以我想我会更新它以反映我在新版本的Python中这样做的方式:
在concurrent.futures
模块中添加了Python 3.2,它为并行任务提供了高级接口。它提供ThreadPoolExecutor
和ProcessPoolExecutor
,因此您可以使用具有相同API的线程或进程池。
此API的一个好处是,向Executor
提交任务会返回一个Future
对象,该对象将以您提交的可调用对象的返回值结束。
这使得不需要附加queue
对象,这简化了装饰器:
_DEFAULT_POOL = ThreadPoolExecutor()
def threadpool(f, executor=None):
@wraps(f)
def wrap(*args, **kwargs):
return (executor or _DEFAULT_POOL).submit(f, *args, **kwargs)
return wrap
如果没有传入,将使用默认的模块线程池执行器。
用法与以前非常相似:
@threadpool
def long_task(x):
import time
x = x + 5
time.sleep(5)
return x
# does not block, returns Future object
y = long_task(10)
print y
# this blocks, waiting for the result
result = y.result()
print result
如果您使用的是Python 3.4+,那么使用此方法(以及一般的Future对象)的一个非常好的功能是可以将返回的未来包装起来,将其转换为asyncio.Future
asyncio.wrap_future
}。这使得协同程序很容易使用:
result = await asyncio.wrap_future(long_task(10))
如果您不需要访问基础concurrent.Future
对象,则可以在装饰器中包含包装:
_DEFAULT_POOL = ThreadPoolExecutor()
def threadpool(f, executor=None):
@wraps(f)
def wrap(*args, **kwargs):
return asyncio.wrap_future((executor or _DEFAULT_POOL).submit(f, *args, **kwargs))
return wrap
然后,每当你需要从事件循环线程中推出cpu密集或阻塞代码时,你可以把它放在一个装饰函数中:
@threadpool
def some_long_calculation():
...
# this will suspend while the function is executed on a threadpool
result = await some_long_calculation()
答案 3 :(得分:31)
另一种不需要更改现有代码的解决方案:
import Queue
from threading import Thread
def foo(bar):
print 'hello {0}'.format(bar)
return 'foo'
que = Queue.Queue()
t = Thread(target=lambda q, arg1: q.put(foo(arg1)), args=(que, 'world!'))
t.start()
t.join()
result = que.get()
print result
它也可以轻松调整到多线程环境:
import Queue
from threading import Thread
def foo(bar):
print 'hello {0}'.format(bar)
return 'foo'
que = Queue.Queue()
threads_list = list()
t = Thread(target=lambda q, arg1: q.put(foo(arg1)), args=(que, 'world!'))
t.start()
threads_list.append(t)
# Add more threads here
...
threads_list.append(t2)
...
threads_list.append(t3)
...
# Join all the threads
for t in threads_list:
t.join()
# Check thread's return value
while not que.empty():
result = que.get()
print result
答案 4 :(得分:17)
Parris / kindall的answer join
/ return
回复移植到Python 3:
from threading import Thread
def foo(bar):
print('hello {0}'.format(bar))
return "foo"
class ThreadWithReturnValue(Thread):
def __init__(self, group=None, target=None, name=None, args=(), kwargs=None, *, daemon=None):
Thread.__init__(self, group, target, name, args, kwargs, daemon=daemon)
self._return = None
def run(self):
if self._target is not None:
self._return = self._target(*self._args, **self._kwargs)
def join(self):
Thread.join(self)
return self._return
twrv = ThreadWithReturnValue(target=foo, args=('world!',))
twrv.start()
print(twrv.join()) # prints foo
注意,{3}中的Thread
类的实现方式不同。
答案 5 :(得分:16)
我偷走了所有人的答案并将其清理干净了一点。
关键部分是将* args和** kwargs添加到join()以处理超时
class threadWithReturn(Thread):
def __init__(self, *args, **kwargs):
super(threadWithReturn, self).__init__(*args, **kwargs)
self._return = None
def run(self):
if self._Thread__target is not None:
self._return = self._Thread__target(*self._Thread__args, **self._Thread__kwargs)
def join(self, *args, **kwargs):
super(threadWithReturn, self).join(*args, **kwargs)
return self._return
以下更新的答案
这是我最受欢迎的答案,因此我决定使用将在py2和py3上运行的代码进行更新。
此外,我看到这个问题的许多答案表明对Thread.join()缺乏理解。有些完全无法处理timeout
arg。但是,当你有(1)可以返回None
的目标函数和(2)你也传递timeout
arg加入时,你应该知道一个例子。 )。请参阅“测试4”以了解此角落案例。
与py2和py3一起使用的ThreadWithReturn类:
import sys
from threading import Thread
from builtins import super # https://stackoverflow.com/a/30159479
if sys.version_info >= (3, 0):
_thread_target_key = '_target'
_thread_args_key = '_args'
_thread_kwargs_key = '_kwargs'
else:
_thread_target_key = '_Thread__target'
_thread_args_key = '_Thread__args'
_thread_kwargs_key = '_Thread__kwargs'
class ThreadWithReturn(Thread):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._return = None
def run(self):
target = getattr(self, _thread_target_key)
if not target is None:
self._return = target(*getattr(self, _thread_args_key), **getattr(self, _thread_kwargs_key))
def join(self, *args, **kwargs):
super().join(*args, **kwargs)
return self._return
一些样本测试如下所示:
import time, random
# TEST TARGET FUNCTION
def giveMe(arg, seconds=None):
if not seconds is None:
time.sleep(seconds)
return arg
# TEST 1
my_thread = ThreadWithReturn(target=giveMe, args=('stringy',))
my_thread.start()
returned = my_thread.join()
# (returned == 'stringy')
# TEST 2
my_thread = ThreadWithReturn(target=giveMe, args=(None,))
my_thread.start()
returned = my_thread.join()
# (returned is None)
# TEST 3
my_thread = ThreadWithReturn(target=giveMe, args=('stringy',), kwargs={'seconds': 5})
my_thread.start()
returned = my_thread.join(timeout=2)
# (returned is None) # because join() timed out before giveMe() finished
# TEST 4
my_thread = ThreadWithReturn(target=giveMe, args=(None,), kwargs={'seconds': 5})
my_thread.start()
returned = my_thread.join(timeout=random.randint(1, 10))
您能否确定我们可能在TEST 4中遇到的角落?
问题是我们希望giveMe()返回None(参见TEST 2),但我们也期望join()在超时时返回None。
returned is None
表示:
(1)这就是giveMe()返回的内容,或
(2)join()超时
这个例子很简单,因为我们知道giveMe()将始终返回None。但是在现实世界中(目标可以合法地返回None或其他东西)我们想要明确检查发生了什么。
以下是解决这个问题的方法:
# TEST 4
my_thread = ThreadWithReturn(target=giveMe, args=(None,), kwargs={'seconds': 5})
my_thread.start()
returned = my_thread.join(timeout=random.randint(1, 10))
if my_thread.isAlive():
# returned is None because join() timed out
# this also means that giveMe() is still running in the background
pass
# handle this based on your app's logic
else:
# join() is finished, and so is giveMe()
# BUT we could also be in a race condition, so we need to update returned, just in case
returned = my_thread.join()
答案 6 :(得分:14)
我发现的大多数答案都很长,需要熟悉其他模块或高级 Python 功能,除非他们已经熟悉答案所涉及的所有内容,否则会让某人感到困惑。
简化方法的工作代码:
import threading, time, random
class ThreadWithResult(threading.Thread):
def __init__(self, group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None):
def function():
self.result = target(*args, **kwargs)
super().__init__(group=group, target=function, name=name, daemon=daemon)
def function_to_thread(n):
count = 0
while count < 3:
print(f'still running thread {n}')
count +=1
time.sleep(3)
result = random.random()
print(f'Return value of thread {n} should be: {result}')
return result
def main():
thread1 = ThreadWithResult(target=function_to_thread, args=(1,))
thread2 = ThreadWithResult(target=function_to_thread, args=(2,))
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print(thread1.result)
print(thread2.result)
main()
说明:
我想显着简化事情,所以我创建了一个 ThreadWithResult
类并让它继承自 threading.Thread
。 function
中的嵌套函数__init__
调用我们想要保存其值的线程函数,并在线程执行完毕后将该嵌套函数的结果保存为实例属性self.result
。< /p>
创建此实例与创建 threading.Thread
实例相同。将要在新线程上运行的函数传递给 target
参数,将函数可能需要的任何参数传递给 args
参数,并将任何关键字参数传递给 kwargs
参数。< /p>
例如
my_thread = ThreadWithResult(target=my_function, args=(arg1, arg2, arg3))
我认为这比绝大多数答案更容易理解,而且这种方法不需要额外的导入!我包含了 time
和 random
模块来模拟线程的行为,但它们不需要实现 original question 中要求的功能。
我知道我是在问这个问题后回答这个问题的,但我希望这可以在未来帮助更多人!
编辑:我创建了 save-thread-result
PyPI package 以允许您访问上面的相同代码并在项目中重复使用它 (GitHub code is here)。 PyPI 包完全扩展了 threading.Thread
类,因此您也可以在 threading.thread
类上设置您在 ThreadWithResult
上设置的任何属性!
上面的原始答案涵盖了该子类背后的主要思想,但有关详细信息,请参阅 more detailed explanation (from the module docstring) here。
快速使用示例:
pip3 install -U save-thread-result # MacOS/Linux
pip install -U save-thread-result # Windows
python3 # MacOS/Linux
python # Windows
from save_thread_result import ThreadWithResult
# As of Release 0.0.3, you can also specify values for
#`group`, `name`, and `daemon` if you want to set those
# values manually.
thread = ThreadWithResult(
target = my_function,
args = (my_function_arg1, my_function_arg2, ...)
kwargs = {my_function_kwarg1: kwarg1_value, my_function_kwarg2: kwarg2_value, ...}
)
thread.start()
thread.join()
if getattr(thread, 'result', None):
print(thread.result)
else:
# thread.result attribute not set - something caused
# the thread to terminate BEFORE the thread finished
# executing the function passed in through the
# `target` argument
print('ERROR! Something went wrong while executing this thread, and the function you passed in did NOT complete!!')
# seeing help about the class and information about the threading.Thread super class methods and attributes available:
help(ThreadWithResult)
答案 7 :(得分:10)
使用队列:
import threading, queue
def calc_square(num, out_queue1):
l = []
for x in num:
l.append(x*x)
out_queue1.put(l)
arr = [1,2,3,4,5,6,7,8,9,10]
out_queue1=queue.Queue()
t1=threading.Thread(target=calc_square, args=(arr,out_queue1))
t1.start()
t1.join()
print (out_queue1.get())
答案 8 :(得分:6)
我对这个问题的解决方法是将函数和线程包装在一个类中。不需要使用池,队列或c类型变量传递。它也是非阻塞的。你检查状态。请参阅代码末尾如何使用它的示例。
import threading
class ThreadWorker():
'''
The basic idea is given a function create an object.
The object can then run the function in a thread.
It provides a wrapper to start it,check its status,and get data out the function.
'''
def __init__(self,func):
self.thread = None
self.data = None
self.func = self.save_data(func)
def save_data(self,func):
'''modify function to save its returned data'''
def new_func(*args, **kwargs):
self.data=func(*args, **kwargs)
return new_func
def start(self,params):
self.data = None
if self.thread is not None:
if self.thread.isAlive():
return 'running' #could raise exception here
#unless thread exists and is alive start or restart it
self.thread = threading.Thread(target=self.func,args=params)
self.thread.start()
return 'started'
def status(self):
if self.thread is None:
return 'not_started'
else:
if self.thread.isAlive():
return 'running'
else:
return 'finished'
def get_results(self):
if self.thread is None:
return 'not_started' #could return exception
else:
if self.thread.isAlive():
return 'running'
else:
return self.data
def add(x,y):
return x +y
add_worker = ThreadWorker(add)
print add_worker.start((1,2,))
print add_worker.status()
print add_worker.get_results()
答案 9 :(得分:5)
在Python 3.2+中,stdlib concurrent.futures
模块为threading
提供了更高级别的API,包括将返回值或异常从工作线程传递回主线程:
import concurrent.futures
def foo(bar):
print('hello {}'.format(bar))
return 'foo'
with concurrent.futures.ThreadPoolExecutor() as executor:
future = executor.submit(foo, 'world!')
return_value = future.result()
print(return_value)
答案 10 :(得分:3)
考虑 @iman 对 @JakeBiesinger 回答的评论我已将其重新组合成各种数量的线程:
from multiprocessing.pool import ThreadPool
def foo(bar, baz):
print 'hello {0}'.format(bar)
return 'foo' + baz
numOfThreads = 3
results = []
pool = ThreadPool(numOfThreads)
for i in range(0, numOfThreads):
results.append(pool.apply_async(foo, ('world', 'foo'))) # tuple of args for foo)
# do some other stuff in the main process
# ...
# ...
results = [r.get() for r in results]
print results
pool.close()
pool.join()
干杯,
盖。
答案 11 :(得分:2)
join
总是返回None
,我认为您应该将Thread
子类化以处理返回代码等等。
答案 12 :(得分:2)
您可以在线程函数的范围之上定义一个mutable,并将结果添加到该函数。 (我还修改了代码为python3兼容)
returns = {}
def foo(bar):
print('hello {0}'.format(bar))
returns[bar] = 'foo'
from threading import Thread
t = Thread(target=foo, args=('world!',))
t.start()
t.join()
print(returns)
这会返回{'world!': 'foo'}
如果您使用函数输入作为结果字典的键,则每个唯一输入都保证在结果中输入
答案 13 :(得分:2)
您可以将Pool用作工作流程池,如下所示:
from multiprocessing import Pool
def f1(x, y):
return x*y
if __name__ == '__main__':
with Pool(processes=10) as pool:
result = pool.apply(f1, (2, 3))
print(result)
答案 14 :(得分:1)
我正在使用这个包装器,它可以轻松地在Thread
中运行任何函数 - 处理它的返回值或异常。它不会增加Queue
开销。
def threading_func(f):
"""Decorator for running a function in a thread and handling its return
value or exception"""
def start(*args, **kw):
def run():
try:
th.ret = f(*args, **kw)
except:
th.exc = sys.exc_info()
def get(timeout=None):
th.join(timeout)
if th.exc:
raise th.exc[0], th.exc[1], th.exc[2] # py2
##raise th.exc[1] #py3
return th.ret
th = threading.Thread(None, run)
th.exc = None
th.get = get
th.start()
return th
return start
def f(x):
return 2.5 * x
th = threading_func(f)(4)
print("still running?:", th.is_alive())
print("result:", th.get(timeout=1.0))
@threading_func
def th_mul(a, b):
return a * b
th = th_mul("text", 2.5)
try:
print(th.get())
except TypeError:
print("exception thrown ok.")
threading
模块舒适的回报价值&amp;线程函数的异常处理是频繁的“Pythonic”需求,并且应该已经由threading
模块提供 - 可能直接在标准Thread
类中提供。 ThreadPool
对于简单的任务来说有太多的开销 - 3个管理线程,大量的官僚作风。不幸的是,Thread
的布局最初是从Java复制的 - 您可以看到,例如来自仍无用的1st(!)构造函数参数group
。
答案 15 :(得分:1)
如前所述,多处理池比基本线程慢得多。在这里使用一些答案提出的队列是一个非常有效的选择。我已经将它与字典一起使用,以便能够运行许多小线程并通过将它们与字典组合来恢复多个答案:
#!/usr/bin/env python3
import threading
# use Queue for python2
import queue
import random
LETTERS = 'abcdefghijklmnopqrstuvwxyz'
LETTERS = [ x for x in LETTERS ]
NUMBERS = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
def randoms(k, q):
result = dict()
result['letter'] = random.choice(LETTERS)
result['number'] = random.choice(NUMBERS)
q.put({k: result})
threads = list()
q = queue.Queue()
results = dict()
for name in ('alpha', 'oscar', 'yankee',):
threads.append( threading.Thread(target=randoms, args=(name, q)) )
threads[-1].start()
_ = [ t.join() for t in threads ]
while not q.empty():
results.update(q.get())
print(results)
答案 16 :(得分:1)
GuySoft的想法很棒,但我认为该对象不一定要从Thread继承而且start()可以从界面中删除:
from threading import Thread
import queue
class ThreadWithReturnValue(object):
def __init__(self, target=None, args=(), **kwargs):
self._que = queue.Queue()
self._t = Thread(target=lambda q,arg1,kwargs1: q.put(target(*arg1, **kwargs1)) ,
args=(self._que, args, kwargs), )
self._t.start()
def join(self):
self._t.join()
return self._que.get()
def foo(bar):
print('hello {0}'.format(bar))
return "foo"
twrv = ThreadWithReturnValue(target=foo, args=('world!',))
print(twrv.join()) # prints foo
答案 17 :(得分:1)
基于kindall提到的内容,这是适用于Python3的更通用的解决方案。
import threading
class ThreadWithReturnValue(threading.Thread):
def __init__(self, *init_args, **init_kwargs):
threading.Thread.__init__(self, *init_args, **init_kwargs)
self._return = None
def run(self):
self._return = self._target(*self._args, **self._kwargs)
def join(self):
threading.Thread.join(self)
return self._return
用法
th = ThreadWithReturnValue(target=requests.get, args=('http://www.google.com',))
th.start()
response = th.join()
response.status_code # => 200
答案 18 :(得分:0)
为什么不只使用全局变量?
import threading
class myThread(threading.Thread):
def __init__(self, ind, lock):
threading.Thread.__init__(self)
self.ind = ind
self.lock = lock
def run(self):
global results
with self.lock:
results.append(self.ind)
results = []
lock = threading.Lock()
threads = [myThread(x, lock) for x in range(1, 4)]
for t in threads:
t.start()
for t in threads:
t.join()
print(results)
答案 19 :(得分:0)
非常简单的方法可以为像我这样的假人做到这一点:
import queue
import threading
# creating queue instance
q = queue.Queue()
# creating threading class
class AnyThread():
def __init__ (self):
threading.Thread.__init__(self)
def run(self):
# in this class and function we will put our test target function
test()
t = AnyThread()
# having our test target function
def test():
# do something in this function:
result = 3 + 2
# and put result to a queue instance
q.put(result)
for i in range(3): #calling our threading fucntion 3 times (just for example)
t.run()
output = q.get() # here we get output from queue instance
print(output)
>>> 5
>>> 5
>>> 5
这里的主要内容是queue
模块。我们创建queue.Queue()
实例并将其包含在我们的函数中。我们用我们的结果提供它,后来我们超越了线程。
请参阅我们的测试函数传递参数的另一个例子:
import queue
import threading
# creating queue instance
q = queue.Queue()
# creating threading class
class AnyThread():
def __init__ (self):
threading.Thread.__init__(self)
def run(self, a, b):
# in this class and function we will put our execution test function
test(a, b)
t = AnyThread()
# having our test target function
def test(a, b):
# do something in this function:
result = a + b
# and put result to a queue instance
q.put(result)
for i in range(3): #calling our threading fucntion 3 times (just for example)
t.run(3+i, 2+i)
output = q.get() # here we get output from queue instance
print(output)
>>> 5
>>> 7
>>> 9
答案 20 :(得分:0)
一个通常的解决方案是使用像
这样的装饰器包裹你的函数foo
result = queue.Queue()
def task_wrapper(*args):
result.put(target(*args))
然后整个代码看起来像那样
result = queue.Queue()
def task_wrapper(*args):
result.put(target(*args))
threads = [threading.Thread(target=task_wrapper, args=args) for args in args_list]
for t in threads:
t.start()
while(True):
if(len(threading.enumerate()) < max_num):
break
for t in threads:
t.join()
return result
一个重要问题是返回值可能无序。
(事实上,return value
未必保存到queue
,因为您可以选择任意线程安全数据结构)
答案 21 :(得分:0)
class ThreadWithReturnValue(Thread):
def __init__(self, group=None, target=None, name=None,
args=(), kwargs={}, *, daemon=None):
Thread.__init__(self, group, target, name, args, kwargs, daemon)
self._return = None
def run(self):
try:
if self._target:
self._return = self._target(*self._args, **self._kwargs)
finally:
del self._target, self._args, self._kwargs
def join(self,timeout=None):
Thread.join(self,timeout)
return self._return
答案 22 :(得分:0)
如果仅要从函数调用中验证True或False,我发现一个更简单的解决方案是更新全局列表。
import threading
lists = {"A":"True", "B":"True"}
def myfunc(name: str, mylist):
for i in mylist:
if i == 31:
lists[name] = "False"
return False
else:
print("name {} : {}".format(name, i))
t1 = threading.Thread(target=myfunc, args=("A", [1, 2, 3, 4, 5, 6], ))
t2 = threading.Thread(target=myfunc, args=("B", [11, 21, 31, 41, 51, 61], ))
t1.start()
t2.start()
t1.join()
t2.join()
for value in lists.values():
if value == False:
# Something is suspicious
# Take necessary action
当您要查找是否有任何线程返回了错误状态以采取必要的操作时,这将更为有用。
答案 23 :(得分:0)
这是我为@Kindall的答案https://stackoverflow.com/a/6894023/12900787
创建的版本(我还提供了一些测试)
这是使用python 3.8制作的
from threading import Thread
from typing import Any
#def threader(com): # my original Version (Ignore this)
# try:
# threader = Thread(target = com)
# threader.start()
# except Exception as e:
# print(e)
# print('Could not start thread')
def test(plug, plug2, plug3):
print(f"hello {plug}")
print(f'I am the second plug : {plug2}')
print(plug3)
return 'I am the return Value!'
def test2(msg):
return f'I am from the second test: {msg}'
def test3():
print('hello world')
def NewThread(com, Returning: bool, *arguments) -> Any:
"""
Will create a new thread for a function/command.
:param com: Command to be Executed
:param arguments: Arguments to be sent to Command
:param Returning: True/False Will this command need to return anything
"""
class NewThreadWorker(Thread):
def __init__(self, group = None, target = None, name = None, args = (), kwargs = None, *,
daemon = None):
Thread.__init__(self, group, target, name, args, kwargs, daemon = daemon)
self._return = None
def run(self):
if self._target is not None:
self._return = self._target(*self._args, **self._kwargs)
def join(self):
Thread.join(self)
return self._return
ntw = NewThreadWorker(target = com, args = (*arguments,))
ntw.start()
if Returning:
return ntw.join()
if __name__ == "__main__":
# threader(test('world'))
print(NewThread(test, True, 'hi', 'test', test2('hi')))
NewThread(test3, True)
希望这对某人有用:)
答案 24 :(得分:0)
将目标定义为
1)采取论据q
2)用return foo
q.put(foo); return
所以功能
def func(a):
ans = a * a
return ans
会变成
def func(a, q):
ans = a * a
q.put(ans)
return
然后你会继续这样做
from Queue import Queue
from threading import Thread
ans_q = Queue()
arg_tups = [(i, ans_q) for i in xrange(10)]
threads = [Thread(target=func, args=arg_tup) for arg_tup in arg_tups]
_ = [t.start() for t in threads]
_ = [t.join() for t in threads]
results = [q.get() for _ in xrange(len(threads))]
您可以使用函数装饰器/包装器来实现它,这样您就可以将现有函数用作target
而无需修改它们,但请遵循此基本方案。
答案 25 :(得分:-1)
我知道这个线程很旧。...但是我遇到了同样的问题...如果您愿意使用thread.join()
import threading
class test:
def __init__(self):
self.msg=""
def hello(self,bar):
print('hello {}'.format(bar))
self.msg="foo"
def main(self):
thread = threading.Thread(target=self.hello, args=('world!',))
thread.start()
thread.join()
print(self.msg)
g=test()
g.main()