ProgrammatiePython ontwikkelaar

Wat gebeurt er bij het doorgeven van samengestelde objecten (zoals lijsten van dictionaries) tussen threads of processen in Python? Waar is het belangrijk om op te letten bij het programmeren van multi-threaded en multi-process applicaties die verband houden met wijzigbare collecties?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord.

In Python zijn objecten in het geheugen beschikbaar voor alle threads zonder kopiëren. Echter, bij het werken met processen via multiprocessing worden standaard Python-objecten (zoals lijsten, dictionaries) tussen processen doorgegeven via serialisatie (meestal via pickle), en elke proces krijgt zijn eigen kopie van het object. Wijzigingen in een object in één proces worden niet weerspiegeld in de kopie in een ander proces.

Belangrijkste verschillen:

  • Multithreading (threading): Alle threads werken in een gemeenschappelijk adresruimte. Alle objecten (inclusief geneste collecties) worden gedeeld.
  • Multiprocessing: Elke proces heeft zijn eigen geheugen; objecten worden doorgegeven via serialisatie. Voor communicatie tussen processen moeten speciale structuren worden gebruikt, zoals multiprocessing.Manager().dict().

Voorbeeld:

# Multiprocessing from multiprocessing import Process, Manager def worker(d): d['a'] = 42 if __name__ == '__main__': # Eenvoudige dict werkt niet tussen processen managed_dict = Manager().dict() p = Process(target=worker, args=(managed_dict,)) p.start(); p.join() print(managed_dict['a']) # 42
  • Als een gewone dict zou worden gebruikt, zouden wijzigingen in het proces niet zichtbaar zijn in het hoofdproces.

Vragend met een val.

In welke gevallen zal het bewerken van een gewone lijst (list) in één proces zichtbaar zijn in een ander proces?

Antwoord:

Nooit, als je werkt met multiprocessing. Gewone Python-objecten worden niet gedeeld tussen processen. Voor delen moeten speciale primitive worden gebruikt — Manager-objecten (bijvoorbeeld, Manager().list(), Manager().dict()), die de status tussen processen synchroniseren.

Voorbeelden van echte fouten vanwege onbekendheid met de subtiliteiten van het onderwerp.


Verhaal

Het team van ontwikkelaars van een web-crawler initialiseerde taakqueues als lijsten en verdeelde deze tussen processen via multiprocessing. Taken “raakten kwijt” omdat processen elkaars updates niet zagen. Dit werd opgelost door gebruik te maken van Manager().list().


Verhaal

In een analytische dienst werden logs geprobeerd te verzamelen in geneste dicts binnen threads. Bij een hoge belasting leidde dit tot race conditions en datacorruptie door een gebrek aan locks.


Verhaal

In een ETL-dienst, bij het proberen om objecten die tijdens de verwerkingsfase zijn verzameld in meerdere processen te verzamelen, ontdekten ze duplicatie/verlies van gegevens: programmeurs hielden geen rekening met het feit dat elk proces met zijn eigen kopie van de structuur werkte en niet met een gezamenlijke.