0Pricing
Python Academy · Lekcja

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, a map() 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 with obsł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

  1. Wątki i GIL
  2. ThreadPoolExecutor
  3. Podstawy multiprocessing
  4. Bezpieczne współdzielenie danych
← Powrót do Python Academy