」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > python 並發.futures

python 並發.futures

發佈於2024-11-08
瀏覽:255

python concurrent.futures

未来

Future 是一个容器,可以保存计算结果或计算期间发生的错误。创建 future 时,它​​以 PENDING 状态开始。该库不打算手动创建此对象,除非出于测试目的。

import concurrent.futures as futures

f = futures.Future()
assert(f._result is None)
assert(f._exception is None)
assert(f._state == 'PENDING')

PENDING 状态表示用户请求的计算已在线程池中注册并放入队列中,但尚未被任何线程拾取执行。一旦空闲线程从队列中获取任务(回调),Future 就会转换为 RUNNING 状态。 Future 只能在处于 PENDING 状态时被取消。因此,在 PENDING 和 RUNNING 状态之间存在一个时间窗口,在此期间可以取消请求的计算。

import concurrent.futures as futures

def should_cancel_pending_future():
    f = futures.Future()
    assert(f._state == 'PENDING')
    assert(f.cancel())
    assert(f._state == 'CANCELLED')

def should_not_cancel_running_future():
    f = futures.Future()
    f.set_running_or_notify_cancel()
    assert(f._state == 'RUNNING')
    assert(not f.cancel())

def cancel_is_idempotent():
    f = futures.Future()
    assert(f.cancel())
    assert(f.cancel())


should_cancel_pending_future()
should_not_cancel_running_future()
cancel_is_idempotent()

线程池中请求的操作可以完成计算值或导致错误。无论结果如何,未来都会过渡到 FINISHED 状态。然后将结果或错误存储在相应的字段中。

import concurrent.futures as futures

def future_completed_with_result():
    f = futures.Future()
    f.set_result('foo')
    assert(f._state == 'FINISHED')
    assert(f._result == 'foo')
    assert(f._exception is None)

def future_completed_with_exception():
    f = futures.Future()
    f.set_exception(NameError())
    assert(f._state == 'FINISHED')
    assert(f._result is None)
    assert(isinstance(f._exception, NameError))

future_completed_with_result()
future_completed_with_exception()

要检索计算结果,请使用 result 方法。如果计算尚未完成,此方法将阻塞当前线程(从中调用结果),直到计算完成或等待超时。

如果计算成功完成且没有错误,则 result 方法返回计算值。

import concurrent.futures as futures
import time
import threading

f = futures.Future()
def target():
    time.sleep(1)
    f.set_result('foo')
threading.Thread(target=target).start()
assert(f.result() == 'foo')

如果计算过程中发生异常,结果将引发该异常。

import concurrent.futures as futures
import time
import threading

f = futures.Future()
def target():
    time.sleep(1)
    f.set_exception(NameError)
threading.Thread(target=target).start()
try:
    f.result()
    raise Exception()
except NameError:
    assert(True)

如果方法在等待时超时,则会引发 TimeoutError。

import concurrent.futures as futures

f = futures.Future()
try:
    f.result(1)
    raise Exception()
except TimeoutError:
    assert(f._result is None)
    assert(f._exception is None)

尝试获取已取消的计算结果将引发 CancelledError。

import concurrent.futures as futures

f = futures.Future()
assert(f.cancel())
try:
    f.result()
    raise Exception()
except futures.CancelledError:
    assert(True)

等待策略

在开发过程中,需要在一个线程池上运行N次计算并等待其完成是很常见的。为了实现这一点,该库提供了等待函数。等待策略有几种:FIRST_COMPLETED、FIRST_EXCEPTION、ALL_COMPLETED。

所有等待策略的共同点是,如果传递给 wait 方法的 future 已经完成,则无论选择何种策略,都会返回传递的 future 的集合。无论它们是如何完成的,无论是有错误、结果还是被取消,都无关紧要。

import concurrent.futures as futures

def test(return_when):
    f1, f2, f3 = futures.Future(), futures.Future(), futures.Future()
    f1.cancel()
    f1.set_running_or_notify_cancel() # required
    f2.set_result('foo')
    f3.set_exception(NameError)

    r = futures.wait([f1, f2, f3], return_when=return_when)
    assert(len(r.done) == 3)
    assert(len(r.not_done) == 0)

for return_when in [futures.ALL_COMPLETED, futures.FIRST_EXCEPTION, futures.FIRST_COMPLETED]:
    test(return_when)

ALL_COMPLETED 策略

ALL_COMPLETED 策略保证等待所有传递的 future 完成,或者在超时后退出,并收集截至该时刻完成的 future,这可能是不完整的。

import concurrent.futures as futures
import threading
import time

def should_wait_for_all_futures_to_complete():
    f1 = futures.Future()
    f1.set_result('foo')
    f2 = futures.Future()

    def target():
        time.sleep(1)
        f2.set_result('bar')

    threading.Thread(target=target).start()
    r = futures.wait([f1, f2], return_when=futures.ALL_COMPLETED)
    assert(len(r.done) == 2)

def should_exit_on_timeout():
    f1 = futures.Future()
    f1.set_result('foo')
    f2 = futures.Future()
    r = futures.wait(fs=[f1, f2], timeout=1, return_when=futures.ALL_COMPLETED)
    assert(len(r.done) == 1)


should_wait_for_all_futures_to_complete()
should_exit_on_timeout()

FIRST_COMPLETED

FIRST_COMPLETED 策略保证返回至少有一个已完成的 future 的集合,或者在超时的情况下返回空集合。 此策略并不意味着返回的集合不能包含多个元素.

import concurrent.futures as futures
import threading
import time

f1 = futures.Future()
f2 = futures.Future()

def target():
    time.sleep(1)
    f1.set_result(True)

threading.Thread(target=target).start()

r = futures.wait([f1, f2], return_when=futures.FIRST_COMPLETED)
assert(len(r.done) == 1)
assert(len(r.not_done) == 1)

FIRST_EXCEPTION

如果其中一个计算完成时出现错误,FIRST_EXCEPTION 策略会中断等待。如果没有发生异常,则行为与 ALL_COMPLETED future 相同。

import concurrent.futures as futures
import threading
import time

f1 = futures.Future()
f1.set_result('foo')
f2, f3 = futures.Future(), futures.Future()

def target():
    time.sleep(1)
    f2.set_exception(NameError())

threading.Thread(target=target).start()

r = futures.wait(fs=[f1, f2, f3], return_when=futures.FIRST_EXCEPTION)
assert(len(r.done) == 2)

线程池执行器

该对象负责创建线程池。与该对象交互的主要方法是 Submit 方法。它允许在线程池中注册计算。作为响应,返回一个 Future 对象,用于监控计算状态并获取最终结果。

特性

  • 仅根据需要创建新线程:
    • 如果请求计算时至少有一个空闲线程,则不会创建新线程
    • 如果请求计算时没有空闲线程,则在未达到 maxWorkers 限制的情况下创建一个新线程。
    • 如果没有空闲线程并且已达到 maxWorkers 限制,则计算将被放入队列中并由下一个可用线程执行
  • 默认情况下为计算需求分配的最大线程数等于逻辑处理器核心数
  • 线程一旦创建,即使在低负载的情况下也不会被销毁
版本聲明 本文轉載於:https://dev.to/mapogolions/python-concurrentfutures-5f4a?1如有侵犯,請聯絡[email protected]刪除
最新教學 更多>
  • 如何正確迭代 getElementsByClassName 並避免不可預測的行為?
    如何正確迭代 getElementsByClassName 並避免不可預測的行為?
    透過 getElementsByClassName 正確迭代使用網頁時,透過類別名稱存取元素是一項常見任務。 getElementsByClassName 方法提供一個 NodeList,它表示匹配元素的集合。但是,迭代 NodeList 可能很棘手,尤其是在修改 DOM 時。 在您的情況下,您嘗試...
    程式設計 發佈於2024-12-22
  • 儘管程式碼有效,為什麼 POST 請求無法擷取 PHP 中的輸入?
    儘管程式碼有效,為什麼 POST 請求無法擷取 PHP 中的輸入?
    解決PHP 中的POST 請求故障在提供的程式碼片段中:action=''而非:action="<?php echo $_SERVER['PHP_SELF'];?>";?>"檢查$_POST陣列:表單提交後使用 var_dump 檢查 $_POST 陣列的內...
    程式設計 發佈於2024-12-22
  • 為什麼 Go 中 `func` 後面有括號?
    為什麼 Go 中 `func` 後面有括號?
    理解Go中func後面括號的意義作為Go程式領域的新手,你可能會遇到在func關鍵字後面直接使用括號的情況。這可能會令人困惑,特別是如果您不熟悉 Go 獨特的語法。讓我們來解釋一下這個看似神祕的功能。 背後是什麼(v 版)? 在 Go 中,func 後面的括號不是函數簽章的一部分,而是表示方法。方法...
    程式設計 發佈於2024-12-22
  • 如何放寬 PHP 中的 open_basedir 限制?
    如何放寬 PHP 中的 open_basedir 限制?
    放寬 PHP 的 open_basedir 限制PHP 的 open_basedir 限制限制對指定目錄樹的檔案存取。但是,在管理 Web 根目錄以外的檔案時,此限制可能會成為障礙。為了解決這個問題,您可以實施多種解決方法。 一種方法是修改 Apache 的設定檔(例如 httpd.conf),以在...
    程式設計 發佈於2024-12-22
  • 隨機鹽如何合併到 Bcrypt 密碼儲存中?
    隨機鹽如何合併到 Bcrypt 密碼儲存中?
    隨機鹽在Bcrypt 密碼儲存中的作用bcrypt 是一種強大的密碼雜湊演算法,它結合了隨機產生的鹽來增強密碼安全性。了解鹽如何整合到 bcrypt 中對於理解其功能至關重要。 bcrypt 演算法需要多個輸入:密碼、工作負載因子和鹽。鹽是隨機產生的字元序列,對於每個密碼雜湊都是唯一的。它透過防止預...
    程式設計 發佈於2024-12-22
  • 如何在Windows上存取XAMPP命令列?
    如何在Windows上存取XAMPP命令列?
    如何在Windows上存取XAMPP的命令列安裝了XAMPP的Windows用戶經常會遇到一個問題:如何存取XAMPP的命令列XAMPP 的命令列?這使得可以直接從命令提示字元執行諸如“php phpfile.php”之類的命令。 解決方案:XAMPP 不提供內建命令列介面。相反,您需要配置 Win...
    程式設計 發佈於2024-12-22
  • 如何按多列升序和降序對 Pandas DataFrame 進行排序?
    如何按多列升序和降序對 Pandas DataFrame 進行排序?
    按多列對 Pandas Dataframe 進行排序按多列對 Pandas Dataframe 進行排序是資料分析中的常見操作。考慮一個包含「a」、「b」和「c」列的資料框。若要按「b」列升序和「c」列降序對此資料框進行排序,請依照下列步驟操作:從Pandas 版本0.17.0 開始,排序方法已被棄...
    程式設計 發佈於2024-12-22
  • 在 Go 中使用 WebSocket 進行即時通信
    在 Go 中使用 WebSocket 進行即時通信
    构建需要实时更新的应用程序(例如聊天应用程序、实时通知或协作工具)需要一种比传统 HTTP 更快、更具交互性的通信方法。这就是 WebSockets 发挥作用的地方!今天,我们将探讨如何在 Go 中使用 WebSocket,以便您可以向应用程序添加实时功能。 在这篇文章中,我们将介绍: WebSoc...
    程式設計 發佈於2024-12-22
  • 如何修復 MySQL 連線錯誤 (2000):mysqlnd 無法使用舊式驗證進行連線?
    如何修復 MySQL 連線錯誤 (2000):mysqlnd 無法使用舊式驗證進行連線?
    克服「連線錯誤(2000):mysqlnd無法使用舊式驗證連接到MySQL 4.1」障礙連接到MySQL資料庫舊的身份驗證方案可能會觸發「連線錯誤(2000)」錯誤。要解決此問題,請考慮以下步驟:1.評估伺服器密碼架構運行SQL 查詢「SHOW VARIABLES LIKE 'old_pas...
    程式設計 發佈於2024-12-22
  • 如何在 PHP 中使用 Glob() 按副檔名高效過濾文件
    如何在 PHP 中使用 Glob() 按副檔名高效過濾文件
    使用 PHP 按副檔名有效率地過濾檔案使用 scandir() 函式從 PHP 目錄擷取檔案清單非常簡單。然而,當您需要根據特定副檔名(例如 .ini)過濾掉檔案時,有效的方法至關重要。 PHP 中的 glob() 函數為此類過濾提供了最佳化的解決方案。它接受一個模式作為參數並傳回與該模式相符的路徑...
    程式設計 發佈於2024-12-22
  • 為什麼 C++ 會拋出「類別不存在預設建構函式」錯誤,以及如何修復它?
    為什麼 C++ 會拋出「類別不存在預設建構函式」錯誤,以及如何修復它?
    理解C 中的「類別不存在預設建構子」錯誤在C 中進行物件導向程式設計時,遇到與預設建構子相關的錯誤並不罕見。本綜合指南將幫助您理解並解決「類別不存在預設建構子」問題。 問題描述嘗試實例化時出現「類別不存在預設建構子」錯誤類別的對象,而不向其建構子提供必要的參數。預設建構函數是一個特殊的成員函數,當未...
    程式設計 發佈於2024-12-22
  • 為什麼 GCC 4.6.1 難以處理 std::array 的初始化清單?
    為什麼 GCC 4.6.1 難以處理 std::array 的初始化清單?
    在 std::array 中使用初始化清單可以透過多種方式使用初始化清單建立 std::array。然而,GCC 4.6.1 嘗試此操作時可能會遇到錯誤。 初始化語法使用初始化清單建立std::array 的語法為:std::array<T, size> array = { { valu...
    程式設計 發佈於2024-12-22
  • 如何在 ASP.NET UpdatePanel 中可靠地處理 jQuery 事件?
    如何在 ASP.NET UpdatePanel 中可靠地處理 jQuery 事件?
    使用jQuery 的$(document).ready 處理UpdatePanel 中的事件使用jQuery 處理UpdatePanel 中的元素時,僅依賴$ ( document).ready 事件綁定可能還不夠。部分頁面更新後,這些事件處理程序將不再在更新區域內執行。 推薦方法要解決此問題,請考...
    程式設計 發佈於2024-12-22
  • 為什麼 `console.log(element.children)` 最初顯示長度為 0,但擴充後顯示為 3 條?
    為什麼 `console.log(element.children)` 最初顯示長度為 0,但擴充後顯示為 3 條?
    element.children的Console.log顯示0長度,但稍後展開時有3個條目程式設計中,了解物件的狀態至關重要。使用 console.log 檢查元素時,了解它如何顯示物件非常重要。 console.log 根據物件的目前狀態動態更新其顯示。最初,當您記錄元素的子元素 (element...
    程式設計 發佈於2024-12-22
  • 如何將 jQuery UI Sortable 與資料庫整合以維持順序?
    如何將 jQuery UI Sortable 與資料庫整合以維持順序?
    jQuery UI Sortable 和資料庫整合使用 jQuery UI Sortable,您可以讓使用者重新排列元素並保持特定的順序。若要將此功能與資料庫集成,您可以結合使用序列化方法和 AJAX 或表單提交。 $('#sortable').sortable({ axis: 'y', ...
    程式設計 發佈於2024-12-22

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3