Hướng dẫn python threadpoolexecutor global variable - biến toàn cục threadpoolexecutor trong python
Tôi mới song song hóa nói chung và đồng thời. Đặc biệt. Tôi muốn đánh giá tập lệnh của mình và so sánh sự khác biệt giữa việc sử dụng các luồng và quy trình, nhưng tôi thấy rằng tôi thậm chí không thể chạy điều đó vì khi sử dụng Show Mã sau đây sẽ xuất ra 0 cho ProcessPoolExecutor , nó sẽ xuất ra 2.
Tôi không hiểu tại sao đây là trường hợp. Trong chương trình thực của tôi, init được sử dụng để đặt các biến toàn cầu thành các đối số CLI và có rất nhiều trong số chúng. Do đó, thông qua chúng như những lập luận dường như không được khuyến nghị. Vậy làm cách nào để chuyển các biến toàn cầu đó cho từng quy trình/luồng một cách chính xác? Tôi biết rằng tôi có thể thay đổi mọi thứ xung quanh, điều này sẽ hoạt động, nhưng tôi không hiểu tại sao. Ví dụ. Các hoạt động sau đây cho cả hai người thực thi, nhưng điều đó cũng có nghĩa là việc khởi tạo toàn cầu phải xảy ra cho mọi trường hợp.
Vì vậy, câu hỏi chính của tôi là, những gì đang thực sự xảy ra. Tại sao mã này hoạt động với các chủ đề chứ không phải với các quy trình? Và, làm thế nào để tôi truyền chính xác các toàn cầu đã đặt cho từng quy trình/luồng mà không cần phải khởi tạo lại chúng cho mọi trường hợp?what is actually happening. Why does this code work with threads and not with processes? And, how do I correctly pass set globals to each process/thread without having to re-initialise them for every instance? (Lưu ý bên: Vì tôi đã đọc rằng đồng thời. Lớn lên khi một hoạt động được thực hiện trong một tương lai không được phép trong trạng thái hiện tại. Mới trong phiên bản 3.8. Lib/concurrent/futures/thread.py and Lib/concurrent/futures/process.py ExceptionConcurrent.futures.thread.brokenthreadpool¶ Có nguồn gốc từ 35, lớp ngoại lệ này được nâng lên khi một trong những công nhân của 4 đã thất bại khi khởi tạo.Tính khả dụng: Không phải emscripten, không phải wasi.: not Emscripten, not WASI. Mô -đun này không hoạt động hoặc không có sẵn trên các nền tảng Webassugging 7 và 8. Xem các nền tảng Webassugging để biết thêm thông tin.WebAssembly platforms for more information.Đối tượng thực thiclassconceren.futures.executor¶ 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 bê tông của nó.
ThreadPoolExecutor¶ 4 là một lớp con 6 sử dụng một nhóm các luồng để thực hiện các cuộc gọi không đồng bộ.Các bế tắc có thể xảy ra khi cuộc gọi có thể gọi được liên quan đến with ThreadPoolExecutor(max_workers=1) as executor: future = executor.submit(pow, 323, 1235) print(future.result())0 chờ kết quả của một with ThreadPoolExecutor(max_workers=1) as executor: future = executor.submit(pow, 323, 1235) print(future.result())0 khác. Ví dụ:
import time def wait_on_b(): time.sleep(5) print(b.result()) # b will never complete because it is waiting on a. return 5 def wait_on_a(): time.sleep(5) print(a.result()) # a will never complete because it is waiting on b. return 6 executor = ThreadPoolExecutor(max_workers=2) a = executor.submit(wait_on_b) b = executor.submit(wait_on_a) And: def wait_on_future(): f = executor.submit(pow, 5, 2) # This will never complete because there is only one worker thread and # it is executing this function. print(f.result()) executor = ThreadPoolExecutor(max_workers=1) executor.submit(wait_on_future)ClassConcienconcurrent.futures.ThreadPoolExecutor(max_workers=None, thread_name_prefix='', initializer=None, initargs=())¶ Một lớp con 6 sử dụng một nhóm tại hầu hết 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 luồng được tính đến 4 sẽ được tham gia trước khi trình thông dịch có thể thoát. Lưu ý rằng trình xử lý thoát mà thực hiện điều này được thực thi trước khi bất kỳ trình xử lý thoát nào được thêm bằng import time def wait_on_b(): time.sleep(5) print(b.result()) # b will never complete because it is waiting on a. return 5 def wait_on_a(): time.sleep(5) print(a.result()) # a will never complete because it is waiting on b. return 6 executor = ThreadPoolExecutor(max_workers=2) a = executor.submit(wait_on_b) b = executor.submit(wait_on_a)5. Điều này có nghĩa là các trường hợp ngoại lệ trong luồng chính phải được bắt 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, khuyến nghị rằng 4 không được sử dụng cho các nhiệm vụ chạy dài.Khởi tạo là một cuộc gọi tùy chọn có thể gọi được gọi là bắt đầu mỗi luồng công nhân; initargs là một bộ phận đối số được chuyển cho trình khởi tạo. Nếu khởi tạo tăng một ngoại lệ, tất cả các công việc hiện đang chờ xử lý sẽ tăng import time def wait_on_b(): time.sleep(5) print(b.result()) # b will never complete because it is waiting on a. return 5 def wait_on_a(): time.sleep(5) print(a.result()) # a will never complete because it is waiting on b. return 6 executor = ThreadPoolExecutor(max_workers=2) a = executor.submit(wait_on_b) b = executor.submit(wait_on_a)7, cũng như bất kỳ nỗ lực nào để gửi thêm công việc lên nhóm. Đã thay đổi trong phiên bản 3.5: Nếu MAX_Workers là with ThreadPoolExecutor(max_workers=1) as executor: future = executor.submit(pow, 323, 1235) print(future.result())5 or not given, it will default to the number of processors on the machine, multiplied by import time def wait_on_b(): time.sleep(5) print(b.result()) # b will never complete because it is waiting on a. return 5 def wait_on_a(): time.sleep(5) print(a.result()) # a will never complete because it is waiting on b. return 6 executor = ThreadPoolExecutor(max_workers=2) a = executor.submit(wait_on_b) b = executor.submit(wait_on_a)9, assuming that 4 is often used to overlap I/O instead of CPU work and the number of workers should be higher than the number of workers for 5.Mới trong phiên bản 3.6: Đối số Thread_NAME_PREFIX đã được thêm vào để cho phép người dùng kiểm soát tên def wait_on_future(): f = executor.submit(pow, 5, 2) # This will never complete because there is only one worker thread and # it is executing this function. print(f.result()) executor = ThreadPoolExecutor(max_workers=1) executor.submit(wait_on_future)2 names for worker threads created by the pool for easier debugging. Đã thay đổi trong phiên bản 3.7: Đã thêm các đối số khởi tạo và khởi đầu.Added the initializer and initargs arguments. Đã thay đổi trong phiên bản 3.8: Giá trị mặc định của MAX_Workers được thay đổi thành def wait_on_future(): f = executor.submit(pow, 5, 2) # This will never complete because there is only one worker thread and # it is executing this function. print(f.result()) executor = ThreadPoolExecutor(max_workers=1) executor.submit(wait_on_future)3. This default value preserves at least 5 workers for I/O bound tasks. It utilizes at most 32 CPU cores for CPU bound tasks which release the GIL. And it avoids using very large resources implicitly on many-core machines. ThreadPoolExecutor bây giờ tái sử dụng các chủ đề công nhân nhàn rỗi trước khi bắt đầu chủ đề công nhân max_workers. Ví dụ về ThreadPoolExecutorimport concurrent.futures import urllib.request URLS = ['http://www.foxnews.com/', 'http://www.cnn.com/', 'http://europe.wsj.com/', 'http://www.bbc.co.uk/', 'http://some-made-up-domain.com/'] # Retrieve a single page and report the URL and contents def load_url(url, timeout): with urllib.request.urlopen(url, timeout=timeout) as conn: return conn.read() # We can use a with statement to ensure threads are cleaned up promptly with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor: # Start the load operations and mark each future with its URL future_to_url = {executor.submit(load_url, url, 60): url for url in URLS} for future in concurrent.futures.as_completed(future_to_url): url = future_to_url[future] try: data = future.result() except Exception as exc: print('%r generated an exception: %s' % (url, exc)) else: print('%r page is %d bytes' % (url, len(data))) ProcessPoolExecutor¶Lớp 5 là một lớp con 6 sử dụng một nhóm quy trình để thực hiện các cuộc gọi không đồng bộ. 5 sử dụng mô-đun def wait_on_future(): f = executor.submit(pow, 5, 2) # This will never complete because there is only one worker thread and # it is executing this function. print(f.result()) executor = ThreadPoolExecutor(max_workers=1) executor.submit(wait_on_future)7, cho phép nó bước phụ của khóa phiên dịch toàn cầu nhưng cũng có nghĩa là chỉ các đối tượng có thể chọn có thể được thực thi và trả về.Global Interpreter Lock but also means that only picklable objects can be executed and returned. Mô -đun def wait_on_future(): f = executor.submit(pow, 5, 2) # This will never complete because there is only one worker thread and # it is executing this function. print(f.result()) executor = ThreadPoolExecutor(max_workers=1) executor.submit(wait_on_future)8 phải được nhập khẩu bởi các quy trình phụ của công nhân. Điều này có nghĩa là 5 sẽ không hoạt động trong trình thông dịch tương tác.Gọi các phương thức 6 hoặc with ThreadPoolExecutor(max_workers=1) as executor: future = executor.submit(pow, 323, 1235) print(future.result())0 từ một cuộc gọi có thể gọi được gửi đến 5 sẽ dẫn đến bế tắc. ClassConcien
concurrent.futures.ProcessPoolExecutor(max_workers=None, mp_context=None, initializer=None,
initargs=(), max_tasks_per_child=None)¶Một lớp con 6 thực hiện các cuộc gọi không đồng bộ bằng cách sử dụng một nhóm tại hầu hết các quy trình MAX_Workers. Nếu MAX_Workers là with ThreadPoolExecutor(max_workers=1) as executor: future = executor.submit(pow, 323, 1235) print(future.result())5 hoặc không được đưa ra, nó sẽ mặc định với số lượng bộ xử lý trên máy. Nếu MAX_Workers nhỏ hơn hoặc bằng import concurrent.futures import urllib.request URLS = ['http://www.foxnews.com/', 'http://www.cnn.com/', 'http://europe.wsj.com/', 'http://www.bbc.co.uk/', 'http://some-made-up-domain.com/'] # Retrieve a single page and report the URL and contents def load_url(url, timeout): with urllib.request.urlopen(url, timeout=timeout) as conn: return conn.read() # We can use a with statement to ensure threads are cleaned up promptly with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor: # Start the load operations and mark each future with its URL future_to_url = {executor.submit(load_url, url, 60): url for url in URLS} for future in concurrent.futures.as_completed(future_to_url): url = future_to_url[future] try: data = future.result() except Exception as exc: print('%r generated an exception: %s' % (url, exc)) else: print('%r page is %d bytes' % (url, len(data)))5, thì import concurrent.futures import urllib.request URLS = ['http://www.foxnews.com/', 'http://www.cnn.com/', 'http://europe.wsj.com/', 'http://www.bbc.co.uk/', 'http://some-made-up-domain.com/'] # Retrieve a single page and report the URL and contents def load_url(url, timeout): with urllib.request.urlopen(url, timeout=timeout) as conn: return conn.read() # We can use a with statement to ensure threads are cleaned up promptly with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor: # Start the load operations and mark each future with its URL future_to_url = {executor.submit(load_url, url, 60): url for url in URLS} for future in concurrent.futures.as_completed(future_to_url): url = future_to_url[future] try: data = future.result() except Exception as exc: print('%r generated an exception: %s' % (url, exc)) else: print('%r page is %d bytes' % (url, len(data)))6 sẽ được nâng lên. Trên Windows, MAX_Workers phải nhỏ hơn hoặc bằng import concurrent.futures import urllib.request URLS = ['http://www.foxnews.com/', 'http://www.cnn.com/', 'http://europe.wsj.com/', 'http://www.bbc.co.uk/', 'http://some-made-up-domain.com/'] # Retrieve a single page and report the URL and contents def load_url(url, timeout): with urllib.request.urlopen(url, timeout=timeout) as conn: return conn.read() # We can use a with statement to ensure threads are cleaned up promptly with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor: # Start the load operations and mark each future with its URL future_to_url = {executor.submit(load_url, url, 60): url for url in URLS} for future in concurrent.futures.as_completed(future_to_url): url = future_to_url[future] try: data = future.result() except Exception as exc: print('%r generated an exception: %s' % (url, exc)) else: print('%r page is %d bytes' % (url, len(data)))7. Nếu không phải thì import concurrent.futures import urllib.request URLS = ['http://www.foxnews.com/', 'http://www.cnn.com/', 'http://europe.wsj.com/', 'http://www.bbc.co.uk/', 'http://some-made-up-domain.com/'] # Retrieve a single page and report the URL and contents def load_url(url, timeout): with urllib.request.urlopen(url, timeout=timeout) as conn: return conn.read() # We can use a with statement to ensure threads are cleaned up promptly with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor: # Start the load operations and mark each future with its URL future_to_url = {executor.submit(load_url, url, 60): url for url in URLS} for future in concurrent.futures.as_completed(future_to_url): url = future_to_url[future] try: data = future.result() except Exception as exc: print('%r generated an exception: %s' % (url, exc)) else: print('%r page is %d bytes' % (url, len(data)))6 sẽ được nâng lên. Nếu MAX_Workers là with ThreadPoolExecutor(max_workers=1) as executor: future = executor.submit(pow, 323, 1235) print(future.result())5, thì được chọn mặc định sẽ nhiều nhất là import concurrent.futures import urllib.request URLS = ['http://www.foxnews.com/', 'http://www.cnn.com/', 'http://europe.wsj.com/', 'http://www.bbc.co.uk/', 'http://some-made-up-domain.com/'] # Retrieve a single page and report the URL and contents def load_url(url, timeout): with urllib.request.urlopen(url, timeout=timeout) as conn: return conn.read() # We can use a with statement to ensure threads are cleaned up promptly with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor: # Start the load operations and mark each future with its URL future_to_url = {executor.submit(load_url, url, 60): url for url in URLS} for future in concurrent.futures.as_completed(future_to_url): url = future_to_url[future] try: data = future.result() except Exception as exc: print('%r generated an exception: %s' % (url, exc)) else: print('%r page is %d bytes' % (url, len(data)))7, ngay cả khi có nhiều bộ xử lý có sẵn. MP_Context có thể là một bối cảnh đa xử lý hoặc không có. Nó sẽ được sử dụng để ra mắt công nhân. Nếu mp_context là with ThreadPoolExecutor(max_workers=1) as executor: future = executor.submit(pow, 323, 1235) print(future.result())5 hoặc không được đưa ra, bối cảnh đa xử lý mặc định được sử dụng. Khởi tạo là một cuộc gọi tùy chọn có thể gọi được khi bắt đầu mỗi quá trình công nhân; initargs là một bộ phận đối số được chuyển cho trình khởi tạo. Nếu khởi tạo tăng một ngoại lệ, tất cả các công việc hiện đang chờ xử lý sẽ tăng import concurrent.futures import math PRIMES = [ 112272535095293, 112582705942171, 112272535095293, 115280095190773, 115797848077099, 1099726899285419] def is_prime(n): if n < 2: return False if n == 2: return True if n % 2 == 0: return False sqrt_n = int(math.floor(math.sqrt(n))) for i in range(3, sqrt_n + 1, 2): if n % i == 0: return False return True def main(): with concurrent.futures.ProcessPoolExecutor() as executor: for number, prime in zip(PRIMES, executor.map(is_prime, PRIMES)): print('%d is prime: %s' % (number, prime)) if __name__ == '__main__': main()2, cũng như bất kỳ nỗ lực nào để gửi thêm công việc lên 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 duy nhất có thể thực hiện trước khi nó sẽ thoát và được thay thế bằng quy trình công nhân mới. Theo mặc định MAX_TASKS_PER_CHILD là with ThreadPoolExecutor(max_workers=1) as executor: future = executor.submit(pow, 323, 1235) print(future.result())5 có nghĩa là các quy trình công nhân sẽ sống miễn là nhóm. Khi tối đa được chỉ định, phương thức bắt đầu đa xử lý của Spawn Spawn 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 bắt đầu của Fork Fork. Đã thay đổi trong phiên bản 3.3: Khi một trong những công nhân xử lý chấm dứt đột ngột, lỗi import concurrent.futures import math PRIMES = [ 112272535095293, 112582705942171, 112272535095293, 115280095190773, 115797848077099, 1099726899285419] def is_prime(n): if n < 2: return False if n == 2: return True if n % 2 == 0: return False sqrt_n = int(math.floor(math.sqrt(n))) for i in range(3, sqrt_n + 1, 2): if n % i == 0: return False return True def main(): with concurrent.futures.ProcessPoolExecutor() as executor: for number, prime in zip(PRIMES, executor.map(is_prime, PRIMES)): print('%d is prime: %s' % (number, prime)) if __name__ == '__main__': main()2 error is now raised. Previously, behaviour was undefined but operations on the executor or its futures would often freeze or deadlock. Đã 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 start_method cho các quy trình công nhân được tạo bởi nhóm.The mp_context argument was added to allow users to control the start_method for worker processes created by the pool. Đã thêm các đối số khởi tạo 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 tuổi thọ của công nhân trong nhóm.The max_tasks_per_child argument was added to allow users to control the lifetime of workers in the pool. ProcessPoolExecutor Ví dụ Enimport concurrent.futures import math PRIMES = [ 112272535095293, 112582705942171, 112272535095293, 115280095190773, 115797848077099, 1099726899285419] def is_prime(n): if n < 2: return False if n == 2: return True if n % 2 == 0: return False sqrt_n = int(math.floor(math.sqrt(n))) for i in range(3, sqrt_n + 1, 2): if n % i == 0: return False return True def main(): with concurrent.futures.ProcessPoolExecutor() as executor: for number, prime in zip(PRIMES, executor.map(is_prime, PRIMES)): print('%d is prime: %s' % (number, prime)) if __name__ == '__main__': main() Đối tượng tương lai lorLớp with ThreadPoolExecutor(max_workers=1) as executor: future = executor.submit(pow, 323, 1235) print(future.result())0 gói gọn việc thực hiện không đồng bộ của một người có thể gọi được. Các trường hợp with ThreadPoolExecutor(max_workers=1) as executor: future = executor.submit(pow, 323, 1235) print(future.result())0 được tạo bởi with ThreadPoolExecutor(max_workers=1) as executor: future = executor.submit(pow, 323, 1235) print(future.result())8. classconceren.futures.future¶concurrent.futures.Future¶ Đóng gói việc thực hiện không đồng bộ của một người có thể gọi được. Các trường hợp with ThreadPoolExecutor(max_workers=1) as executor: future = executor.submit(pow, 323, 1235) print(future.result())0 được tạo bởi with ThreadPoolExecutor(max_workers=1) as executor: future = executor.submit(pow, 323, 1235) print(future.result())8 và không nên được tạo trực tiếp ngoại trừ thử nghiệm.
Các phương pháp with ThreadPoolExecutor(max_workers=1) as executor: future = executor.submit(pow, 323, 1235) print(future.result())0 sau đây được sử dụng trong các thử nghiệm đơn vị và triển khai 6.
set_exception (ngoại lệ) ¶Đặt kết quả của công việc liên quan đếnwith ThreadPoolExecutor(max_workers=1) as executor: future = executor.submit(pow, 323, 1235) print(future.result())0 thành ngoại lệ Hello 2.wait(fs, timeout=None,
return_when=ALL_COMPLETED)¶Chức năng mô -đun đồng thời. Đợi các trường hợp with ThreadPoolExecutor(max_workers=1) as executor: future = executor.submit(pow, 323, 1235) print(future.result())0 (có thể được tạo bởi các trường hợp 6 khác nhau) được đưa ra bởi FS để hoàn thành. Tương lai trùng lặp được trao cho FS được loại bỏ và sẽ chỉ được trả lại một lần. Trả về một bộ 2 được đặt tên. Bộ đầu tiên, được đặt tên là 18, chứa tương lai đã hoàn thành (hoàn thành hoặc hủy bỏ tương lai) trước khi chờ đợi hoàn thành. Bộ thứ hai, được đặt tên là 19, chứa tương lai không hoàn thành (tương lai đang chờ xử lý hoặc chạy).
23.as_completed(fs, timeout=None)¶
Hàm sẽ trở lại khi tất cả các kết thúc tương lai hoặc bị hủy. đồng thời.futures.as_completed (fs, thời gian chờ = không) Trả về một trình lặp trong các trường hợpwith ThreadPoolExecutor(max_workers=1) as executor: future = executor.submit(pow, 323, 1235) print(future.result())0 (có thể được tạo bởi các trường hợp 6 khác nhau) được đưa ra bởi FS mang lại tương lai khi chúng hoàn thành (hoàn thành hoặc hủy bỏ tương lai). Bất kỳ tương lai nào được đưa ra bởi FS được sao chép sẽ được trả lại một lần. Bất kỳ tương lai nào đã hoàn thành trước khi 03 được gọi sẽ được mang lại trước. Trình lặp được trả về tăng with ThreadPoolExecutor(max_workers=1) as executor: future = executor.submit(pow, 323, 1235) print(future.result())2 nếu with ThreadPoolExecutor(max_workers=1) as executor: future = executor.submit(pow, 323, 1235) print(future.result())3 được gọi và kết quả không có sẵn sau khi hết thời gian chờ từ cuộc gọi ban đầu đến 03. Thời gian chờ có thể là một int hoặc float. Nếu thời gian chờ không được chỉ định hoặc with ThreadPoolExecutor(max_workers=1) as executor: future = executor.submit(pow, 323, 1235) print(future.result())5, không có giới hạn thời gian chờ. – futures - execute computations asynchronously Xem thêm PEP 3148 - Tương lai - Thực thi tính toán không đồng bộĐề xuất mô tả tính năng này để đưa vào thư viện tiêu chuẩn Python.concurrent.futures.CancelledError¶Các lớp ngoại lệ ngoại lệConcurrent.futures.cancelledError¶concurrent.futures.TimeoutError¶Lớn lên khi một tương lai bị hủy bỏ. ngoại lệConcurrent.Futures.TimeouterRor¶This class was made an alias of with ThreadPoolExecutor(max_workers=1) as executor: future = executor.submit(pow, 323, 1235) print(future.result())2. Một bí danh không dùng nữa của with ThreadPoolExecutor(max_workers=1) as executor: future = executor.submit(pow, 323, 1235) print(future.result())2, được nâng lên khi một hoạt động trong tương lai vượt quá thời gian chờ đã cho. concurrent.futures.BrokenExecutor¶ Thay đổi trong phiên bản 3.11: Lớp này được tạo thành bí danh là with ThreadPoolExecutor(max_workers=1) as executor: future = executor.submit(pow, 323, 1235) print(future.result())2. Mới trong phiên bản 3.7. ExceptionConcireconcurrent.futures.InvalidStateError¶Lớn lên khi một hoạt động được thực hiện trong một tương lai không được phép trong trạng thái hiện tại. Mới trong phiên bản 3.8. ExceptionConcurrent.futures.thread.brokenthreadpool¶concurrent.futures.thread.BrokenThreadPool¶Có nguồn gốc từ 35, lớp ngoại lệ này được nâng lên khi một trong những công nhân của 4 đã thất bại khi khởi tạo.Mới trong phiên bản 3.7. ExceptionConcire concurrent.futures.process.BrokenProcessPool¶Có nguồn gốc từ 35 (trước đây là import shutil with ThreadPoolExecutor(max_workers=4) as 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')0), lớp ngoại lệ này được nâng lên khi một trong những công nhân của 5 đã chấm dứt theo kiểu không có tội phạm (ví dụ, nếu nó bị giết từ bên ngoài).Mới trong phiên bản 3.3. |