ThreadPoolExecutor
Uruchamiaj zadania współbieżnie
ThreadPoolExecutor to bezpłatna lekcja Python Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Python Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Python Academy zawiera 4 lekcji w sumie.
Po co korzystać z puli wątków
Ręczne tworzenie wątków i oczekiwanie na ich zakończenie jest żmudne. concurrent.futures.ThreadPoolExecutor zarządza za Ciebie pulą wątków roboczych i przejrzyście zwraca wyniki.
from concurrent.futures import ThreadPoolExecutor
def square(n):
return n * n
with ThreadPoolExecutor() as ex:
future = ex.submit(square, 5)
print(future.result())submit i Future
submit() planuje wywołanie i natychmiast zwraca obiekt Future. Aby pobrać wartość, należy wywołać na nim .result(); wywołanie to blokuje działanie do momentu, gdy wynik będzie gotowy.
from concurrent.futures import ThreadPoolExecutor
def greet(name):
return 'hi ' + name
with ThreadPoolExecutor(max_workers=2) as ex:
f1 = ex.submit(greet, 'Ana')
f2 = ex.submit(greet, 'Bob')
print(f1.result())
print(f2.result())map dla wielu danych wejściowych
executor.map(func, iterable) współbieżnie uruchamia funkcję dla każdego elementu i zwraca wyniki w kolejności danych wejściowych.
from concurrent.futures import ThreadPoolExecutor
def cube(n):
return n ** 3
with ThreadPoolExecutor() as ex:
results = ex.map(cube, range(5))
print(list(results))Kontrolowanie liczby pracowników
max_workers ogranicza liczbę wątków uruchomionych jednocześnie. W przypadku zadań ograniczonych przez operacje wejścia-wyjścia można użyć większej liczby pracowników niż liczba rdzeni CPU.
from concurrent.futures import ThreadPoolExecutor
import time
def io_task(n):
time.sleep(0.05)
return n
start = time.perf_counter()
with ThreadPoolExecutor(max_workers=4) as ex:
print(list(ex.map(io_task, range(4))))
print('ran concurrently')as_completed
as_completed(futures) zwraca każdy obiekt future natychmiast po jego zakończeniu, niezależnie od kolejności przesłania zadań. Doskonale nadaje się do przetwarzania wyników od razu po ich otrzymaniu.
from concurrent.futures import ThreadPoolExecutor, as_completed
import time
def work(n):
time.sleep(0.01 * (3 - n))
return n
with ThreadPoolExecutor() as ex:
futures = [ex.submit(work, i) for i in range(3)]
for f in as_completed(futures):
print('finished', f.result())Obsługa wyjątków
Jeśli zadanie zgłosi wyjątek, zostanie on zapisany w jego obiekcie Future i ponownie zgłoszony po wywołaniu .result(). To wywołanie należy umieścić w bloku try/except.
from concurrent.futures import ThreadPoolExecutor
def risky(n):
if n == 0:
raise ValueError('cannot be zero')
return 10 // n
with ThreadPoolExecutor() as ex:
f = ex.submit(risky, 0)
try:
print(f.result())
except ValueError as e:
print('caught:', e)Mapowanie z wieloma argumentami
map akceptuje kilka obiektów iterowalnych i łączy ich elementy w argumenty, podobnie jak wbudowana funkcja map.
from concurrent.futures import ThreadPoolExecutor
def add(a, b):
return a + b
with ThreadPoolExecutor() as ex:
print(list(ex.map(add, [1, 2, 3], [10, 20, 30])))Zbieranie wyników w słowniku
Popularny schemat polega na przypisaniu każdego obiektu Future z powrotem do jego danych wejściowych, aby podczas używania as_completed było wiadomo, którego elementu dotyczy dany wynik.
from concurrent.futures import ThreadPoolExecutor, as_completed
def length(word):
return len(word)
words = ['cat', 'tiger', 'ox']
with ThreadPoolExecutor() as ex:
future_to_word = {ex.submit(length, w): w for w in words}
out = {}
for f in as_completed(future_to_word):
out[future_to_word[f]] = f.result()
print(sorted(out.items()))Zamykanie za pomocą menedżera kontekstu
Użycie executora w bloku with automatycznie wywołuje shutdown() i czeka na zakończenie wszystkich oczekujących zadań.
from concurrent.futures import ThreadPoolExecutor
def job(n):
return n * 2
with ThreadPoolExecutor() as ex:
futures = [ex.submit(job, i) for i in range(3)]
print('all tasks done after the with block')
print([f.result() for f in futures])Sprawdzanie stanu obiektu Future
Obiekt Future udostępnia metody .done() i .running(), dzięki którym można sprawdzać postęp bez blokowania działania.
from concurrent.futures import ThreadPoolExecutor
def quick(n):
return n + 1
with ThreadPoolExecutor() as ex:
f = ex.submit(quick, 41)
result = f.result()
print('done?', f.done())
print('value:', result)Kiedy go używać
ThreadPoolExecutor idealnie nadaje się do wielu niewielkich zadań ograniczonych przez operacje wejścia-wyjścia: żądań HTTP, odczytu plików i zapytań do bazy danych. Do zadań ograniczonych przez CPU należy zamiast tego użyć ProcessPoolExecutor.
from concurrent.futures import ThreadPoolExecutor
urls = ['a', 'b', 'c']
def fetch(u):
return 'fetched ' + u
with ThreadPoolExecutor(max_workers=3) as ex:
for r in ex.map(fetch, urls):
print(r)Szybkie sprawdzenie
Sprawdź, czy rozumiesz działanie ThreadPoolExecutor.
Podsumowanie
Nauczył się Pan / Nauczyła się Pani korzystać z ThreadPoolExecutor:
submit()zwraca obiekt Future, amap()działa na obiekcie iterowalnym w określonej kolejności.as_completed()zwraca obiekty Future w miarę ich kończenia.- Wyjątki są zgłaszane przy użyciu
result(). - Blok
withobsługuje zamykanie puli.
Następnie: prawdziwe wykonywanie równoległe za pomocą multiprocessing.
Często zadawane pytania
Czy lekcja „ThreadPoolExecutor” jest bezpłatna?
Tak — pełny tekst „ThreadPoolExecutor” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Python Academy, przejdź na CoddyKit PRO. Kurs Python Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „ThreadPoolExecutor”?
Uruchamiaj zadania współbieżnie Ćwiczysz Python Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Python Academy?
Nie wymagamy żadnego doświadczenia. Python Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.
Ile czasu zajmuje lekcja „ThreadPoolExecutor”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Python Academy?
Tak. Każda lekcja Python Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Wątki i GIL
- ThreadPoolExecutor
- Podstawy multiprocessing
- Bezpieczne współdzielenie danych