我以前遇到過這個問題:Running multiple asynchronous function and get the returned value of each function。這是我的方法去做:
def async_call(func_list):
"""
Runs the list of function asynchronously.
:param func_list: Expects list of lists to be of format
[[func1, args1, kwargs1], [func2, args2, kwargs2], ...]
:return: List of output of the functions
[output1, output2, ...]
"""
def worker(function, f_args, f_kwargs, queue, index):
"""
Runs the function and appends the output to list, and the Exception in the case of error
"""
response = {
'index': index, # For tracking the index of each function in actual list.
# Since, this function is called asynchronously, order in
# queue may differ
'data': None,
'error': None
}
# Handle error in the function call
try:
response['data'] = function(*f_args, **f_kwargs)
except Exception as e:
response['error'] = e # send back the exception along with the queue
queue.put(response)
queue = Queue()
processes = [Process(target=worker, args=(func, args, kwargs, queue, i)) \
for i, (func, args, kwargs) in enumerate(func_list)]
for process in processes:
process.start()
response_list = []
for process in processes:
# Wait for process to finish
process.join()
# Get back the response from the queue
response = queue.get()
if response['error']:
raise response['error'] # Raise exception if the function call failed
response_list.append(response)
return [content['data'] for content in sorted(response_list, key=lambda x: x['index'])]
採樣運行:
def my_sum(x, y):
return x + y
def your_mul(x, y):
return x*y
my_func_list = [[my_sum, [1], {'y': 2}], [your_mul, [], {'x':1, 'y':2}]]
async_call(my_func_list)
# Value returned: [3, 2]
+1用於分享好的信息。我有一個疑問,如果通過函數引發異常,它的行爲如何?它處理了嗎? –
@Moinuddin根據我的經驗,使用ThreadPoolExcecutors而不是'map'來處理錯誤,您可以使用submit來返回未來,然後在完成後調用future.result()。這會引發任何被發現的例外。 – flybonzai
@flybonzai:亞爾。創建'Future'的'list',然後,如果結果順序很重要,只需循環訪問'list'並調用'result'(包含在'try' /'except'中以處理worker中出現的異常)。如果結果順序無關緊要,[使用'concurrent.futures.as_completed'](https://docs.python.org/3/library/concurrent.futures.html#concurrent.futures.as_completed),這會產生'未來的對象,因爲他們完成(成功或由於例外);再次,你可以在'try' /'except'塊中調用'result'來處理錯誤。如果命令不重要,後者通常更有效率。 – ShadowRanger