如何在非同步結果返回時進行跟蹤

华科云商小雪發表於2024-03-06

當我在使用多程序池時,可以透過 apply_async() 方法提交任務,並使用 get() 方法獲取非同步任務的結果。但是,在等待結果返回時,我們最希望能夠跟蹤任務的進度,以及處理已完成任務的結果。

然後針對這種問題我們最常見的方法是使用回撥函式來處理非同步任務的結果。您可以為每個任務指定一個回撥函式,在任務完成時自動呼叫。這樣,就可以在回撥函式中處理任務的結果,同時也可以跟蹤任務的進度。

1、問題背景:

在多程序池中使用非同步方式提交多個函式作為任務並獲取結果時,通常難以確定每個函式任務對應的結果。本文探討了如何跟蹤非同步結果,以便能夠將每個結果與相應的函式任務聯絡起來。

2、解決方案:

使用工作函式包裝器:

工作函式包裝器可以將原始函式作為引數,並在其周圍新增額外的邏輯。當原始函式作為任務提交到多程序池時,工作函式包裝器會被呼叫,可以在其中捕獲任務的後設資料(如任務的索引、名稱等)。然後,當任務完成並返回結果時,可以在包裝器中將這些後設資料與結果一起儲存在一個字典或元組中。

使用回撥函式:

回撥函式是在任務完成時被呼叫的函式。在使用 apply_async 方法提交任務時,可以指定一個回撥函式。當任務完成時,回撥函式會被呼叫,並將任務的結果作為引數傳遞給回撥函式。在回撥函式中,可以將任務的後設資料和結果儲存在一個字典或元組中。

**使用 AsyncResult 物件:

AsyncResult 物件是 apply_async 方法返回的物件,它包含任務的後設資料和結果。在獲取任務結果時,可以使用 AsyncResult 物件來訪問任務的後設資料和結果。可以使用 AsyncResult 物件的 get 方法來獲取任務結果。

**使用多執行緒或者事件佇列來儲存結果:

在回撥函式中,儲存結果集合的變數是共享資源,但可能多個程序同時訪問,為避免競爭條件(race condition),可以使用執行緒安全的資料型別來儲存結果集合。

下面是一個示例程式碼,演示瞭如何使用上述解決方案之一來跟蹤非同步結果:


import 
multiprocessing

from multiprocessing import Pool
import time

def multiply( x, y):
time. sleep( 1)
return x * y

# 使用工作函式包裝器
def wrapped_multiply( x, y, task_index):
result = multiply( x, y)
return ( task_index, result)

def main():
# 建立一個多程序池
pool = multiprocessing. Pool()

# 提交任務
tasks = [( i, j) for i in range( 1, 11) for j in range( 1, 11)]
results = pool. map( wrapped_multiply, tasks)

# 列印結果
for result in results:
print( f"Task { result[ 0]} result: { result[ 1]} ")

if __name__ == "__main__":
main()

在上面的示例程式碼中, wrapped_multiply 函式是一個工作函式包裝器,它將原始函式 multiply 作為引數,並在其周圍新增了額外的邏輯來捕獲任務的索引。然後,當任務完成並返回結果時, wrapped_multiply 函式將任務的索引和結果儲存在一個元組中。

main 函式建立了一個多程序池,並將任務提交到多程序池。然後, main 函式使用 pool.map 方法來獲取任務的結果。 pool.map 方法會將 tasks 序列中的每個任務提交到多程序池,並返回一個包含任務結果的列表。

最後, main 函式列印每個任務的結果。

在上面的示例程式碼中,我們使用了工作函式包裝器來跟蹤非同步結果。同樣,你也可以使用回撥函式或 AsyncResult 物件來跟蹤非同步結果。

然後再我們在實際應用中,可以根據自身需要對回撥函式進行擴充套件,以處理任務結果的儲存、進度更新等操作。透過使用回撥函式,我們也可以在任務完成時自動觸發相關操作,從而更加方便地進行非同步任務的處理和跟蹤。

上面就是本文的全部內容,希望能夠幫助大家解決在使用多程序池時跟蹤非同步結果的問題。



來自 “ ITPUB部落格 ” ,連結:https://blog.itpub.net/70034537/viewspace-3008201/,如需轉載,請註明出處,否則將追究法律責任。

相關文章