In Python, quando si lavora con thread, gli oggetti in memoria sono accessibili a tutti i thread senza copia. Tuttavia, quando si lavora con processi tramite multiprocessing, gli oggetti standard di Python (ad esempio, liste, dizionari) vengono trasferiti tra i processi tramite serializzazione (di solito tramite pickle), e ogni processo riceve la propria copia dell'oggetto. Le modifiche all'oggetto in un processo non si riflettono sulla copia in un altro processo.
multiprocessing.Manager().dict().# Multiprocessing from multiprocessing import Process, Manager def worker(d): d['a'] = 42 if __name__ == '__main__': # Un dict normale non funziona tra processi managed_dict = Manager().dict() p = Process(target=worker, args=(managed_dict,)) p.start(); p.join() print(managed_dict['a']) # 42
In quali casi la modifica di una lista normale (list) in un processo si rifletterà in un altro processo?
Mai, se si utilizza multiprocessing. Gli oggetti Python normali non sono condivisi tra i processi. Per la condivisione è necessario utilizzare primitive speciali—oggetti Manager (ad esempio, Manager().list(), Manager().dict()), che sincronizzano lo stato tra i processi.
Storia
Il team di sviluppatori di un crawler web ha inizializzato le code di lavori come liste e le ha condivise tra processi tramite multiprocessing. I lavori "scomparivano" perché i processi non vedevano gli aggiornamenti reciproci. Hanno corretto usando Manager().list().
Storia
In un servizio analitico, i registri tentavano di essere raccolti in dizionari annidati all'interno dei thread. In uno scenario ad alta richiesta questo ha portato a condizioni di competizione e danneggiamento dei dati a causa della mancanza di lock.
Storia
In un servizio ETL, quando hanno tentato di raccogliere oggetti di dati raccolti durante la fase di elaborazione in molti processi, hanno scoperto duplicazione/perdita di dati: gli sviluppatori non avevano considerato che ogni processo lavorava con la propria copia della struttura, e non con una comune.