concurrent.futures --- Khởi chạy các tác vụ song song¶
Added in version 3.2.
Source code: Lib/concurrent/futures/thread.py, Lib/concurrent/futures/process.py, và Lib/concurrent/futures/interpreter.py
Mô-đun concurrent.futures cung cấp giao diện cấp cao để thực thi lệnh gọi không đồng bộ.
Việc thực thi không đồng bộ có thể được thực hiện bằng các luồng, sử dụng ThreadPoolExecutor hoặc InterpreterPoolExecutor hoặc các quy trình riêng biệt, sử dụng ProcessPoolExecutor. Mỗi cái thực hiện cùng một giao diện, được xác định bởi lớp Executor trừu tượng.
Không được nhầm lẫn concurrent.futures.Future với asyncio.Future, được thiết kế để sử dụng với các tác vụ và coroutine asyncio. Xem tài liệu asyncio's Future để có sự so sánh chi tiết về cả hai.
sẵn có: not WASI.
Mô-đun này không hoạt động hoặc không có trên WebAssembly. Xem Nền tảng WebAssugging để biết thêm thông tin.
Đối tượng thực thi¶
- class concurrent.futures.Executor¶
Một lớp trừu tượng cung cấp các phương thức để thực hiện các cuộc gọi không đồng bộ. Nó không nên được sử dụng trực tiếp mà thông qua các lớp con cụ thể của nó.
- submit(fn, /, *args, **kwargs)¶
Lập lịch cho đối tượng có thể gọi được, fn, được thực thi dưới dạng
fn(*args, **kwargs)và trả về một đối tượngFuturethể hiện việc thực thi đối tượng có thể gọi được.với ThreadPoolExecutor(max_workers=1) là người thực thi: tương lai = executor.submit(pow, 323, 1235) in(tương lai.result())
- map(fn, *iterables, timeout=None, chunksize=1, buffersize=None)¶
Tương tự như
map(fn, *iterables)ngoại trừ:iterables được thu thập ngay lập tức thay vì một cách lười biếng, trừ khi buffersize được chỉ định để giới hạn số lượng nhiệm vụ được gửi mà chưa mang lại kết quả. Nếu bộ đệm đầy, quá trình lặp qua iterables sẽ tạm dừng cho đến khi có kết quả từ bộ đệm.
fn được thực thi không đồng bộ và một số lệnh gọi đến fn có thể được thực hiện đồng thời.
Trình vòng lặp được trả về sẽ tăng
TimeoutErrornếu__next__()được gọi và kết quả không có sau timeout giây kể từ lệnh gọi ban đầu tớiExecutor.map(). timeout có thể là int hoặc float. Nếu timeout không được chỉ định hoặcNone, sẽ không có giới hạn về thời gian chờ.Nếu lệnh gọi fn đưa ra một ngoại lệ thì ngoại lệ đó sẽ được đưa ra khi giá trị của nó được lấy từ trình vòng lặp.
Khi sử dụng
ProcessPoolExecutor, phương pháp này sẽ chia iterables thành một số phần mà nó gửi tới nhóm dưới dạng các tác vụ riêng biệt. Kích thước (gần đúng) của các khối này có thể được chỉ định bằng cách đặt chunksize thành số nguyên dương. Đối với các lần lặp rất dài, việc sử dụng giá trị lớn cho chunksize có thể cải thiện đáng kể hiệu suất so với kích thước mặc định là 1. VớiThreadPoolExecutorvàInterpreterPoolExecutor, chunksize không có tác dụng.Thay đổi trong phiên bản 3.5: Đã thêm tham số chunksize.
Thay đổi trong phiên bản 3.14: Đã thêm tham số buffersize.
- shutdown(wait=True, *, cancel_futures=False)¶
Báo hiệu cho người thực thi rằng nó sẽ giải phóng mọi tài nguyên mà nó đang sử dụng khi thực thi xong các hợp đồng tương lai hiện đang chờ xử lý. Các lệnh gọi tới
Executor.submit()vàExecutor.map()được thực hiện sau khi tắt máy sẽ tăngRuntimeError.Nếu wait là
Truethì phương thức này sẽ không trả về cho đến khi tất cả các tương lai đang chờ xử lý được thực thi xong và các tài nguyên liên quan đến người thực thi đã được giải phóng. Nếu wait làFalsethì phương thức này sẽ trả về ngay lập tức và các tài nguyên được liên kết với người thực thi sẽ được giải phóng khi tất cả các tương lai đang chờ xử lý được thực thi xong. Bất kể giá trị của wait là bao nhiêu, toàn bộ chương trình Python sẽ không thoát cho đến khi tất cả các hợp đồng tương lai đang chờ xử lý được thực thi xong.Nếu cancel_futures là
True, phương thức này sẽ hủy tất cả các hợp đồng tương lai đang chờ xử lý mà người thi hành chưa bắt đầu chạy. Mọi hợp đồng tương lai đã hoàn thành hoặc đang chạy sẽ không bị hủy, bất kể giá trị của cancel_futures.Nếu cả cancel_futures và wait đều là
Truethì tất cả các hợp đồng tương lai mà người thi hành đã bắt đầu chạy sẽ được hoàn thành trước khi phương thức này quay trở lại. Các hợp đồng tương lai còn lại bị hủy bỏ.Bạn có thể tránh phải gọi phương thức này một cách rõ ràng nếu bạn sử dụng trình thực thi làm context manager thông qua câu lệnh
with, câu lệnh này sẽ tắtExecutor(chờ như thểExecutor.shutdown()được gọi với wait được đặt thànhTrue):nhập khẩu với ThreadPoolExecutor(max_workers=4) là e: e.submit(shutil.copy, 'src1.txt', 'dest1.txt') e.submit(shutil.copy, 'src2.txt', 'dest2.txt') e.submit(shutil.copy, 'src3.txt', 'dest3.txt') e.submit(shutil.copy, 'src4.txt', 'dest4.txt')
Thay đổi trong phiên bản 3.9: Đã thêm cancel_futures.
ThreadPoolExecutor¶
ThreadPoolExecutor là một lớp con Executor sử dụng một nhóm luồng để thực hiện các cuộc gọi không đồng bộ.
Bế tắc có thể xảy ra khi lệnh gọi được liên kết với Future chờ kết quả của Future khác. Ví dụ:
thời gian nhập khẩu
chắc chắn wait_on_b():
thời gian.ngủ(5)
print(b.result()) # b sẽ không bao giờ hoàn thành vì nó đang chờ a.
trở lại 5
chắc chắn wait_on_a():
thời gian.ngủ(5)
print(a.result()) # a sẽ không bao giờ hoàn thành vì nó đang chờ b.
trở lại 6
người thực thi = ThreadPoolExecutor(max_workers=2)
a = executor.submit(wait_on_b)
b = executor.submit(wait_on_a)
Và:
chắc chắn wait_on_future():
f = executor.submit(pow, 5, 2)
# This sẽ không bao giờ hoàn thành vì chỉ có một luồng công nhân và
# it đang thực thi chức năng này.
in(f.result())
người thi hành = ThreadPoolExecutor(max_workers=1)
tương lai = executor.submit(wait_on_future)
# Note: gọi Future.result() cũng sẽ gây ra bế tắc vì
Chuỗi công việc đơn # the đang chờ wait_on_future().
- class concurrent.futures.ThreadPoolExecutor(max_workers=None, thread_name_prefix='', initializer=None, initargs=())¶
Một lớp con
Executorsử dụng một nhóm tối đa các luồng max_workers để thực hiện các cuộc gọi không đồng bộ.Tất cả các chủ đề được xếp hàng vào
ThreadPoolExecutorsẽ được nối trước khi trình thông dịch có thể thoát. Lưu ý rằng trình xử lý thoát thực hiện việc này được thực thi before bất kỳ trình xử lý thoát nào được thêm bằngatexit. Điều này có nghĩa là các ngoại lệ trong luồng chính phải được phát hiện và xử lý để báo hiệu các luồng thoát ra một cách duyên dáng. Vì lý do này, không nên sử dụngThreadPoolExecutorcho các tác vụ chạy trong thời gian dài.initializer là một lệnh gọi tùy chọn được gọi ở đầu mỗi chuỗi công việc; initargs là một bộ đối số được truyền cho bộ khởi tạo. Nếu initializer đưa ra một ngoại lệ, tất cả các công việc hiện đang chờ xử lý sẽ đưa ra
BrokenThreadPool, cũng như mọi nỗ lực gửi thêm công việc vào nhóm.Thay đổi trong phiên bản 3.5: Nếu max_workers là
Nonehoặc không được cung cấp, nó sẽ mặc định là số lượng bộ xử lý trên máy, nhân với5, giả sử rằngThreadPoolExecutorthường được sử dụng để chồng chéo I/O thay vì công việc CPU và số lượng công nhân phải cao hơn số lượng công nhân choProcessPoolExecutor.Thay đổi trong phiên bản 3.6: Đã thêm tham số thread_name_prefix để cho phép người dùng kiểm soát tên
threading.Threadcho các chuỗi công việc do nhóm tạo để gỡ lỗi dễ dàng hơn.Thay đổi trong phiên bản 3.7: Đã thêm đối số initializer và initargs.
Thay đổi trong phiên bản 3.8: Giá trị mặc định của max_workers được đổi thành
min(32, os.cpu_count() + 4). Giá trị mặc định này duy trì ít nhất 5 công nhân cho các tác vụ liên kết I/O. Nó sử dụng tối đa 32 lõi CPU cho các tác vụ ràng buộc CPU giải phóng GIL. Và nó tránh sử dụng ngầm các tài nguyên rất lớn trên các máy nhiều lõi.ThreadPoolExecutor hiện sử dụng lại các luồng công việc nhàn rỗi trước khi bắt đầu các luồng công việc max_workers.
Thay đổi trong phiên bản 3.13: Giá trị mặc định của max_workers được đổi thành
min(32, (os.process_cpu_count() or 1) + 4).
Ví dụ về ThreadPoolExecutor¶
nhập đồng thời.futures
nhập urllib.request
URLS = ['http://www.foxnews.com/',
'http://www.cnn.com/',
'http://europe.wsj.com/',
'http://www.bbc.co.uk/',
'http://nonexistent-subdomain.python.org/']
# Retrieve một trang duy nhất và báo cáo URL và nội dung
def Load_url(url, timeout):
với urllib.request.urlopen(url, timeout=timeout) là kết nối:
trả về conn.read()
# We có thể sử dụng câu lệnh with để đảm bảo các luồng được dọn sạch kịp thời
với concurrent.futures.ThreadPoolExecutor(max_workers=5) là người thực thi:
# Start tải các hoạt động và đánh dấu từng tương lai với URL của nó
Future_to_url = {executor.submit(load_url, url, 60): url cho url trong URLS}
cho tương lai trong concurrent.futures.as_completed(future_to_url):
url = tương lai_to_url[tương lai]
thử:
dữ liệu = tương lai.result()
ngoại trừ Ngoại lệ như exec:
print('%r đã tạo ra một ngoại lệ: %s' % (url, ex))
khác:
print('%r trang is %d bytes' % (url, len(data)))
Thông Dịch ViênPoolNgười Thi Hành¶
Added in version 3.14.
Lớp InterpreterPoolExecutor sử dụng một nhóm trình thông dịch để thực hiện các cuộc gọi không đồng bộ. Nó là lớp con ThreadPoolExecutor, có nghĩa là mỗi công nhân đang chạy trong luồng riêng của mình. Sự khác biệt ở đây là mỗi nhân viên có trình thông dịch riêng và chạy từng tác vụ bằng trình thông dịch đó.
Lợi ích lớn nhất của việc sử dụng trình thông dịch thay vì chỉ các luồng là tính song song đa lõi thực sự. Mỗi trình thông dịch có Global Interpreter Lock riêng, vì vậy mã chạy trong một trình thông dịch có thể chạy trên một lõi CPU, trong khi mã trong một trình thông dịch khác chạy không bị chặn trên một lõi khác.
Sự cân bằng là việc viết mã đồng thời để sử dụng với nhiều trình thông dịch có thể tốn nhiều công sức hơn. Tuy nhiên, điều này là do nó buộc bạn phải thận trọng về cách thức và thời điểm các thông dịch viên tương tác cũng như phải rõ ràng về dữ liệu nào được chia sẻ giữa các thông dịch viên. Điều này mang lại một số lợi ích giúp cân bằng nỗ lực bổ sung, bao gồm cả tính song song đa lõi thực sự. Ví dụ: mã được viết theo cách này có thể giúp bạn dễ dàng suy luận về tính đồng thời hơn. Một lợi ích lớn khác là bạn không phải đối mặt với một số vấn đề lớn khi sử dụng chuỗi, chẳng hạn như điều kiện chạy đua.
Mỗi thông dịch viên của công nhân được tách biệt khỏi tất cả các thông dịch viên khác. "Bị cô lập" có nghĩa là mỗi trình thông dịch có trạng thái thời gian chạy riêng và hoạt động hoàn toàn độc lập. Ví dụ: nếu bạn chuyển hướng sys.stdout trong một trình thông dịch, nó sẽ không tự động được chuyển hướng đến bất kỳ trình thông dịch nào khác. Nếu bạn nhập một mô-đun vào một trình thông dịch, nó sẽ không được tự động nhập vào bất kỳ trình thông dịch nào khác. Bạn sẽ cần nhập mô-đun riêng biệt vào trình thông dịch nơi bạn cần. Trên thực tế, mỗi mô-đun được nhập vào trình thông dịch là một đối tượng hoàn toàn riêng biệt với cùng một mô-đun trong một trình thông dịch khác, bao gồm sys, builtins và thậm chí __main__.
Cách ly có nghĩa là một đối tượng có thể thay đổi hoặc dữ liệu khác không thể được sử dụng bởi nhiều hơn một trình thông dịch cùng một lúc. Điều đó có nghĩa là người phiên dịch thực sự không thể chia sẻ các đối tượng hoặc dữ liệu đó. Thay vào đó, mỗi trình thông dịch phải có bản sao riêng và bạn sẽ phải đồng bộ hóa mọi thay đổi giữa các bản sao theo cách thủ công. Các đối tượng và dữ liệu bất biến, như các đơn vị, chuỗi và bộ dữ liệu dựng sẵn của các đối tượng bất biến, không có những hạn chế này.
Việc giao tiếp và đồng bộ hóa giữa các trình thông dịch được thực hiện hiệu quả nhất bằng cách sử dụng các công cụ chuyên dụng, giống như những công cụ được đề xuất trong PEP 734. Một giải pháp thay thế kém hiệu quả hơn là tuần tự hóa bằng pickle và sau đó gửi byte qua socket hoặc pipe được chia sẻ.
- class concurrent.futures.InterpreterPoolExecutor(max_workers=None, thread_name_prefix='', initializer=None, initargs=())¶
Một lớp con
ThreadPoolExecutorthực hiện các cuộc gọi không đồng bộ bằng cách sử dụng tối đa một nhóm các luồng max_workers. Mỗi luồng chạy các tác vụ trong trình thông dịch riêng của nó. Các trình thông dịch công nhân được tách biệt với nhau, nghĩa là mỗi trình thông dịch có trạng thái thời gian chạy riêng và chúng không thể chia sẻ bất kỳ đối tượng có thể thay đổi hoặc dữ liệu nào khác. Mỗi trình thông dịch có Global Interpreter Lock riêng, có nghĩa là mã chạy với trình thực thi này có tính song song đa lõi thực sự.Các đối số initializer và initargs tùy chọn có cùng ý nghĩa như đối với
ThreadPoolExecutor: trình khởi tạo được chạy khi mỗi công nhân được tạo, mặc dù trong trường hợp này nó được chạy trong trình thông dịch của công nhân. Người thi hành tuần tự hóa initializer và initargs bằng cách sử dụngpicklekhi gửi chúng tới trình thông dịch của công nhân.Ghi chú
Người thi hành có thể thay thế các ngoại lệ chưa được phát hiện từ initializer bằng
ExecutionFailed.Những cảnh báo khác từ
ThreadPoolExecutorgốc được áp dụng tại đây.
submit() và map() hoạt động như bình thường, ngoại trừ trình chạy tuần tự hóa lệnh gọi và đối số bằng cách sử dụng pickle khi gửi chúng tới trình thông dịch của nó. Tương tự, nhân viên sẽ tuần tự hóa giá trị trả về khi gửi lại.
Khi tác vụ hiện tại của một nhân viên đưa ra một ngoại lệ chưa được nắm bắt, nhân viên đó luôn cố gắng duy trì ngoại lệ đó. Nếu thành công thì nó cũng đặt __cause__ thành một phiên bản ExecutionFailed tương ứng, chứa bản tóm tắt về ngoại lệ ban đầu. Trong trường hợp hiếm gặp là nhân viên không thể giữ nguyên bản gốc thì thay vào đó, nó sẽ trực tiếp bảo toàn phiên bản ExecutionFailed tương ứng.
Người thi hành ProcessPool¶
Lớp ProcessPoolExecutor là lớp con Executor sử dụng một nhóm quy trình để thực hiện các cuộc gọi không đồng bộ. ProcessPoolExecutor sử dụng mô-đun multiprocessing, cho phép nó vượt qua Global Interpreter Lock nhưng cũng có nghĩa là chỉ những đối tượng có thể chọn mới có thể được thực thi và trả về.
Mô-đun __main__ phải có thể được nhập bởi các quy trình con của nhân viên. Điều này có nghĩa là ProcessPoolExecutor sẽ không hoạt động trong trình thông dịch tương tác.
Việc gọi các phương thức Executor hoặc Future từ một đối tượng có thể gọi được gửi tới ProcessPoolExecutor sẽ dẫn đến bế tắc.
Lưu ý rằng các hạn chế về hàm và đối số cần có thể chọn theo multiprocessing.Process sẽ được áp dụng khi sử dụng submit() và map() trên ProcessPoolExecutor. Một hàm được xác định trong REPL hoặc lambda sẽ không hoạt động.
- class concurrent.futures.ProcessPoolExecutor(max_workers=None, mp_context=None, initializer=None, initargs=(), max_tasks_per_child=None)¶
Một lớp con
Executorthực hiện các cuộc gọi không đồng bộ bằng cách sử dụng một nhóm gồm nhiều nhất các quy trình max_workers. Nếu max_workers làNonehoặc không được cung cấp, nó sẽ mặc định làos.process_cpu_count(). Nếu max_workers nhỏ hơn hoặc bằng0thìValueErrorsẽ được nâng lên. Trên Windows, max_workers phải nhỏ hơn hoặc bằng61. Nếu không thìValueErrorsẽ được nâng lên. Nếu max_workers làNonethì mặc định được chọn tối đa sẽ là61, ngay cả khi có nhiều bộ xử lý hơn. mp_context có thể là ngữ cảnhmultiprocessinghoặcNone. Nó sẽ được sử dụng để khởi động các công nhân. Nếu mp_context làNonehoặc không được cung cấp thì ngữ cảnhmultiprocessingmặc định sẽ được sử dụng. Xem Bối cảnh và phương pháp bắt đầu.initializer là một lệnh gọi tùy chọn được gọi khi bắt đầu mỗi quy trình công nhân; initargs là một bộ đối số được truyền cho bộ khởi tạo. Nếu initializer đưa ra một ngoại lệ, tất cả các công việc hiện đang chờ xử lý sẽ đưa ra
BrokenProcessPool, cũng như mọi nỗ lực gửi thêm công việc vào nhóm.max_tasks_per_child là một đối số tùy chọn chỉ định số lượng tác vụ tối đa mà một quy trình có thể thực thi trước khi nó thoát ra và được thay thế bằng một quy trình công nhân mới. Theo mặc định, max_tasks_per_child là
None, có nghĩa là các quy trình công nhân sẽ tồn tại lâu như nhóm. Khi mức tối đa được chỉ định, phương thức bắt đầu đa xử lý "sinh sản" sẽ được sử dụng theo mặc định khi không có tham số mp_context. Tính năng này không tương thích với phương pháp khởi động "ngã ba".Ghi chú
Các lỗi đã được báo cáo khi sử dụng tính năng max_tasks_per_child có thể khiến
ProcessPoolExecutorbị treo trong một số trường hợp. Thực hiện theo độ phân giải cuối cùng của nó trong gh-115634.Thay đổi trong phiên bản 3.3: Khi một trong các quy trình công nhân chấm dứt đột ngột, lỗi
BrokenProcessPoolhiện đã xuất hiện. Trước đây, hành vi không được xác định nhưng các hoạt động trên người thực thi hoặc tương lai của nó thường bị đóng băng hoặc bế tắc.Thay đổi trong phiên bản 3.7: Đối số mp_context đã được thêm vào để cho phép người dùng kiểm soát phương thức start_method cho các quy trình công nhân do nhóm tạo.
Đã thêm đối số initializer và initargs.
Thay đổi trong phiên bản 3.11: Đối số max_tasks_per_child đã được thêm vào để cho phép người dùng kiểm soát thời gian hoạt động của các công nhân trong nhóm.
Thay đổi trong phiên bản 3.12: Trên hệ thống POSIX, nếu ứng dụng của bạn có nhiều luồng và ngữ cảnh
multiprocessingsử dụng phương thức khởi động"fork": Hàmos.fork()được gọi nội bộ để sinh ra các nhân viên có thể tạo ra mộtDeprecationWarning. Chuyển mp_context được định cấu hình để sử dụng phương thức khởi động khác. Xem tài liệuos.fork()để được giải thích thêm.Thay đổi trong phiên bản 3.13: max_workers sử dụng
os.process_cpu_count()theo mặc định, thay vìos.cpu_count().Thay đổi trong phiên bản 3.14: Phương thức bắt đầu quy trình mặc định (xem Bối cảnh và phương pháp bắt đầu) đã thay đổi so với fork. Nếu bạn yêu cầu phương thức khởi động fork cho
ProcessPoolExecutor, bạn phải chuyểnmp_context=multiprocessing.get_context("fork")một cách rõ ràng.- terminate_workers()¶
Cố gắng chấm dứt tất cả các quy trình Worker đang hoạt động ngay lập tức bằng cách gọi
Process.terminatetrên mỗi quy trình đó. Trong nội bộ, nó cũng sẽ gọiExecutor.shutdown()để đảm bảo rằng tất cả các tài nguyên khác liên quan đến người thực thi đều được giải phóng.Sau khi gọi phương thức này, người gọi sẽ không gửi nhiệm vụ cho người thực thi nữa.
Added in version 3.14.
- kill_workers()¶
Cố gắng loại bỏ tất cả các quy trình công nhân đang hoạt động ngay lập tức bằng cách gọi
Process.killtrên mỗi quy trình đó. Trong nội bộ, nó cũng sẽ gọiExecutor.shutdown()để đảm bảo rằng tất cả các tài nguyên khác liên quan đến người thực thi đều được giải phóng.Sau khi gọi phương thức này, người gọi sẽ không gửi nhiệm vụ cho người thực thi nữa.
Added in version 3.14.
Ví dụ về ProcessPoolExecutor¶
nhập đồng thời.futures
nhập toán
PRIMES = [
112272535095293,
112582705942171,
112272535095293,
115280095190773,
115797848077099,
1099726899285419]
def is_prime(n):
nếu n < 2:
trả về Sai
nếu n == 2:
trả về Đúng
nếu n% 2 == 0:
trả về Sai
sqrt_n = int(math.floor(math.sqrt(n)))
cho tôi trong phạm vi (3, sqrt_n + 1, 2):
nếu n % i == 0:
trả về Sai
trả về Đúng
chắc chắn chính():
với concurrent.futures.ProcessPoolExecutor() làm người thực thi:
đối với số, số nguyên tố ở dạng zip(PRIMES, executor.map(is_prime, PRIMES)):
print('%d là số nguyên tố: %s' % (số, số nguyên tố))
nếu __name__ == '__main__':
chính()
Đối tượng tương lai¶
Lớp Future gói gọn việc thực thi không đồng bộ của lệnh gọi. Các phiên bản Future được tạo bởi Executor.submit().
- class concurrent.futures.Future¶
Đóng gói việc thực thi không đồng bộ của một lệnh gọi. Các phiên bản
Futuređược tạo bởiExecutor.submit()và không được tạo trực tiếp ngoại trừ để thử nghiệm.- cancel()¶
Cố gắng hủy cuộc gọi. Nếu cuộc gọi hiện đang được thực hiện hoặc chạy xong và không thể hủy thì phương thức sẽ trả về
False, nếu không cuộc gọi sẽ bị hủy và phương thức sẽ trả vềTrue.
- cancelled()¶
Trả về
Truenếu cuộc gọi được hủy thành công.
- running()¶
Trả về
Truenếu cuộc gọi hiện đang được thực hiện và không thể hủy được.
- done()¶
Trả về
Truenếu cuộc gọi bị hủy thành công hoặc chạy xong.
- result(timeout=None)¶
Trả về giá trị được cuộc gọi trả về. Nếu cuộc gọi chưa hoàn thành thì phương thức này sẽ đợi tới timeout giây. Nếu cuộc gọi chưa hoàn thành sau timeout giây thì
TimeoutErrorsẽ được đưa ra. timeout có thể là int hoặc float. Nếu timeout không được chỉ định hoặcNonethì không có giới hạn về thời gian chờ.Nếu tương lai bị hủy trước khi hoàn thành thì
CancelledErrorsẽ được nâng lên.Nếu cuộc gọi đưa ra một ngoại lệ, phương thức này sẽ đưa ra ngoại lệ tương tự.
- exception(timeout=None)¶
Trả lại ngoại lệ được đưa ra bởi cuộc gọi. Nếu cuộc gọi chưa hoàn thành thì phương thức này sẽ đợi tới timeout giây. Nếu cuộc gọi chưa hoàn thành sau timeout giây thì
TimeoutErrorsẽ được đưa ra. timeout có thể là int hoặc float. Nếu timeout không được chỉ định hoặcNonethì không có giới hạn về thời gian chờ.Nếu tương lai bị hủy trước khi hoàn thành thì
CancelledErrorsẽ được nâng lên.Nếu cuộc gọi hoàn tất mà không tăng,
Nonesẽ được trả về.
- add_done_callback(fn)¶
Gắn fn có thể gọi được vào tương lai. fn sẽ được gọi, với tương lai là đối số duy nhất của nó, khi tương lai bị hủy hoặc chạy xong.
Các lệnh gọi đã thêm được gọi theo thứ tự chúng được thêm vào và luôn được gọi trong một luồng thuộc quy trình đã thêm chúng. Nếu lệnh gọi được tạo ra một lớp con
Exception, nó sẽ được ghi lại và bỏ qua. Nếu lệnh gọi có thể tạo ra một lớp conBaseExceptionthì hành vi đó sẽ không được xác định.Nếu tương lai đã hoàn thành hoặc bị hủy, fn sẽ được gọi ngay lập tức.
Các phương pháp
Futuresau đây được sử dụng trong các thử nghiệm đơn vị và triển khaiExecutor.- set_running_or_notify_cancel()¶
Phương pháp này chỉ nên được gọi khi triển khai
Executortrước khi thực hiện công việc liên quan đếnFuturevà bằng các thử nghiệm đơn vị.Nếu phương thức trả về
FalsethìFutuređã bị hủy, tức làFuture.cancel()được gọi và trả vềTrue. Bất kỳ chủ đề nào đang chờFuturehoàn thành (tức là thông quaas_completed()hoặcwait()) sẽ được đánh thức.Nếu phương thức trả về
TruethìFuturekhông bị hủy và được đặt ở trạng thái đang chạy, tức là các lệnh gọi tớiFuture.running()sẽ trả vềTrue.Phương thức này chỉ có thể được gọi một lần và không thể được gọi sau khi
Future.set_result()hoặcFuture.set_exception()được gọi.
- set_result(result)¶
Đặt kết quả của công việc liên quan đến
Futurethành result.Phương pháp này chỉ nên được sử dụng khi triển khai
Executorvà kiểm tra đơn vị.Thay đổi trong phiên bản 3.8: Phương pháp này tăng
concurrent.futures.InvalidStateErrornếuFutuređã được thực hiện.
Chức năng mô-đun¶
- concurrent.futures.wait(fs, timeout=None, return_when=ALL_COMPLETED)¶
Đợi các phiên bản
Future(có thể được tạo bởi các phiên bảnExecutorkhác nhau) do fs cung cấp hoàn tất. Hợp đồng tương lai trùng lặp được cung cấp cho fs sẽ bị xóa và sẽ chỉ được trả lại một lần. Trả về 2 bộ được đặt tên. Tập đầu tiên, có tên làdone, chứa các hợp đồng tương lai đã hoàn thành (các hợp đồng tương lai đã hoàn thành hoặc bị hủy) trước khi quá trình chờ đợi hoàn tất. Bộ thứ hai, có tên lànot_done, chứa các hợp đồng tương lai chưa hoàn thành (các hợp đồng tương lai đang chờ xử lý hoặc đang chạy).timeout có thể được sử dụng để kiểm soát số giây tối đa phải chờ trước khi quay lại. timeout có thể là int hoặc float. Nếu timeout không được chỉ định hoặc
Nonethì không có giới hạn về thời gian chờ.return_when cho biết khi nào hàm này sẽ quay trở lại. Nó phải là một trong các hằng số sau:
Hằng số
Mô tả
- concurrent.futures.FIRST_COMPLETED¶
Hàm sẽ quay trở lại khi bất kỳ thao tác nào trong tương lai kết thúc hoặc bị hủy.
- concurrent.futures.FIRST_EXCEPTION¶
Hàm sẽ trả về khi bất kỳ tương lai nào kết thúc bằng cách đưa ra một ngoại lệ. Nếu không có tương lai nào đưa ra ngoại lệ thì nó tương đương với
ALL_COMPLETED.- concurrent.futures.ALL_COMPLETED¶
Hàm sẽ trả về khi tất cả hợp đồng tương lai kết thúc hoặc bị hủy.
- concurrent.futures.as_completed(fs, timeout=None)¶
Trả về một trình vòng lặp trên các phiên bản
Future(có thể được tạo bởi các phiên bảnExecutorkhác nhau) do fs cung cấp, mang lại tương lai khi chúng hoàn thành (tương lai đã hoàn thành hoặc bị hủy). Bất kỳ hợp đồng tương lai nào do fs cung cấp bị trùng lặp sẽ được trả lại một lần. Bất kỳ hợp đồng tương lai nào hoàn thành trước khias_completed()được gọi sẽ được trả trước. Trình lặp được trả về sẽ tăngTimeoutErrornếu__next__()được gọi và kết quả không có sau timeout giây kể từ lệnh gọi ban đầu tớias_completed(). timeout có thể là int hoặc float. Nếu timeout không được chỉ định hoặcNonethì không có giới hạn về thời gian chờ.
Xem thêm
- PEP 3148 -- tương lai - thực hiện tính toán không đồng bộ
Đề xuất mô tả tính năng này để đưa vào thư viện chuẩn Python.
Các lớp ngoại lệ¶
- exception concurrent.futures.CancelledError¶
Tăng lên khi một tương lai bị hủy bỏ.
- exception concurrent.futures.TimeoutError¶
Bí danh
TimeoutErrorkhông được dùng nữa, được nêu ra khi một thao tác trong tương lai vượt quá thời gian chờ nhất định.Thay đổi trong phiên bản 3.11: Lớp này được đặt bí danh là
TimeoutError.
- exception concurrent.futures.BrokenExecutor¶
Bắt nguồn từ
RuntimeError, lớp ngoại lệ này được nâng lên khi bộ thực thi bị hỏng vì lý do nào đó và không thể được sử dụng để gửi hoặc thực thi các tác vụ mới.Added in version 3.7.
- exception concurrent.futures.InvalidStateError¶
Xảy ra khi một thao tác được thực hiện trong tương lai không được phép ở trạng thái hiện tại.
Added in version 3.8.
- exception concurrent.futures.thread.BrokenThreadPool¶
Bắt nguồn từ
BrokenExecutor, lớp ngoại lệ này được đưa ra khi một trong các công nhân củaThreadPoolExecutorkhởi tạo không thành công.Added in version 3.7.
- exception concurrent.futures.interpreter.BrokenInterpreterPool¶
Bắt nguồn từ
BrokenThreadPool, lớp ngoại lệ này được đưa ra khi một trong các công nhân củaInterpreterPoolExecutorkhởi tạo không thành công.Added in version 3.14.
- exception concurrent.futures.process.BrokenProcessPool¶
Bắt nguồn từ
BrokenExecutor(trước đây làRuntimeError), lớp ngoại lệ này được nâng lên khi một trong các công nhân củaProcessPoolExecutorđã chấm dứt theo kiểu không sạch sẽ (ví dụ: nếu nó bị giết từ bên ngoài).Added in version 3.3.