0Pricing
Python Academy · Lezione

ThreadPoolExecutor

Eseguire attività in concorrenza

ThreadPoolExecutor è una lezione Python Academy gratuita su CoddyKit. Questa è la lezione 2 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Python Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Python Academy include 4 lezioni in totale.

Perché usare un thread pool?

Creare e unire i thread manualmente è tedioso. concurrent.futures.ThreadPoolExecutor gestisce per Lei un pool di thread worker e restituisce i risultati in modo ordinato.

from concurrent.futures import ThreadPoolExecutor

def square(n):
    return n * n

with ThreadPoolExecutor() as ex:
    future = ex.submit(square, 5)
    print(future.result())

submit e Future

submit() pianifica una chiamata e restituisce immediatamente un Future. Lo utilizza con .result() per ottenere il valore, bloccando l'esecuzione finché non è pronto.

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 per molti input

executor.map(func, iterable) esegue la funzione su ogni elemento in concorrenza e produce i risultati nell'ordine degli input.

from concurrent.futures import ThreadPoolExecutor

def cube(n):
    return n ** 3

with ThreadPoolExecutor() as ex:
    results = ex.map(cube, range(5))
    print(list(results))

Controllare il numero di worker

max_workers limita il numero di thread eseguiti contemporaneamente. Per il lavoro I/O-bound può usare più worker del numero di core della 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) produce ogni future non appena termina, indipendentemente dall'ordine di invio. È ideale per elaborare i risultati non appena arrivano.

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())

Gestire le eccezioni

Se un'attività genera un'eccezione, questa viene memorizzata nel relativo Future e generata nuovamente quando chiama .result(). Racchiuda la chiamata in un blocco 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)

Eseguire il mapping con più argomenti

map accetta diversi iterabili e li combina come argomenti, proprio come il built-in 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])))

Raccogliere i risultati in un dizionario

Un modello comune associa ogni future al relativo input, così può sapere a quale input corrisponde ciascun risultato quando usa as_completed.

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()))

Arresto con il context manager

Usare l'executor in un blocco with chiama automaticamente shutdown(), attendendo il completamento di tutte le attività in sospeso.

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])

Controllare lo stato di un Future

Un Future espone .done() e .running(), così può controllare lo stato di avanzamento senza bloccare l'esecuzione.

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)

Quando usarlo

ThreadPoolExecutor è ideale per molte piccole attività I/O-bound: chiamate HTTP, letture di file e query al database. Per il lavoro CPU-bound, usi invece 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)

Verifica rapida

Verifichi la Sua comprensione di ThreadPoolExecutor.

Ripasso

Ha imparato a usare ThreadPoolExecutor:

  • submit() restituisce un Future; map() opera su un iterabile mantenendone l'ordine.
  • as_completed() restituisce i future man mano che terminano.
  • Le eccezioni vengono rese disponibili tramite result().
  • Il blocco with gestisce l'arresto.

Avanti: il vero parallelismo con multiprocessing.

Domande Frequenti

La lezione «ThreadPoolExecutor» è gratuita?

Sì — il testo completo di «ThreadPoolExecutor» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Python Academy, passa a CoddyKit PRO. Il corso Python Academy include 4 lezioni in totale.

Cosa imparerò in «ThreadPoolExecutor»?

Eseguire attività in concorrenza Eserciti Python Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Python Academy?

Non è richiesta alcuna esperienza precedente. Python Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 2 di 4.

Quanto tempo richiede la lezione «ThreadPoolExecutor»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Python Academy?

Sì. Ogni lezione Python Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Thread e GIL
  2. ThreadPoolExecutor
  3. Nozioni di base su multiprocessing
  4. Condividere i dati in sicurezza
← Torna a Python Academy