Archiv verlassen und diese Seite im Standarddesign anzeigen : Python: Class-Member haben in Main-Thread und Background-Thread andere Werte
Matti
2025-04-18, 12:51:47
In folgendem Python-Code wird die Member-Funktion "analyze" parallel ausgeführt und das Ergebnis in self.findings gespeichert. Leider bekomme ich in Main-Thread eine Exception, dass "self" kein Attribut "findings" hat.
class JiraAnalyze:
def __init__(self, pipeline, jira, issue):
doSomething()
def analyze(self):
self.findings = something()
def present(self):
print(self.findings)
def processTickets(pipeline, jira, tickets):
print("Parallel analysis of",len(tickets),"tickets")
analyzers = []
threads = []
for ticket in tickets:
a = JiraAnalyze(pipeline,jira,ticket,True)
analyzers.append(a)
t = Process(target=JiraAnalyze.analyze, args=(a,))
t.start()
threads.append(t)
print("Waiting for background threads to finish")
for t in threads:
t.join()
print("Background threads have finished")
for a in analyzers:
a.present()
Wie kann man das Problem lösen?
Asaraki
2025-04-18, 13:24:21
In dem du beim Aufruf ein Objekt mitgibst, das findings hat ^^
Ist ohne den ganzen Code jetzt müssig zu erklären, aber so dumm es klingt : die Fehlermeldung ist akkurat :D
Chathgbt
Das Verhalten, dass class member unterschiedliche Werte im Hauptprozess und im Hintergrundprozess (Thread) haben, liegt in deinem Fall nicht an Threads, sondern an der Verwendung von multiprocessing.Process.
Hauptursache: multiprocessing.Process erstellt einen neuen Prozess
In Python bedeutet Process aus dem multiprocessing-Modul:
Jeder neue Process ist ein komplett eigener Speicherbereich.
Änderungen an Objekten in einem Kindprozess sind nicht sichtbar im Hauptprozess.
Was passiert genau in deinem Code?
for ticket in tickets:
a = JiraAnalyze(pipeline, jira, ticket, True)
analyzers.append(a)
t = Process(target=JiraAnalyze.analyze, args=(a,))
t.start()
threads.append(t)
Du erzeugst ein Objekt a im Hauptprozess.
Du startest einen neuen Prozess, der JiraAnalyze.analyze(a) aufruft.
Dieser neue Prozess bekommt eine Kopie von a (per Pickle serialisiert).
In analyze() wird self.findings gesetzt, aber nur im Kindprozess.
Nach join() versuchst du im Hauptprozess a.present() aufzurufen.
Da self.findings dort nie gesetzt wurde, kommt AttributeError oder None.
Lösungsmöglichkeiten
1. Verwende threading.Thread, wenn du gemeinsamen Speicher brauchst
from threading import Thread
t = Thread(target=JiraAnalyze.analyze, args=(a,))
Damit bleiben a.findings im Hauptthread und im Thread gleich, weil Speicher geteilt ist.
2. Verwende multiprocessing.Queue, Manager, oder Pipe, um Daten auszutauschen
from multiprocessing import Process, Manager
def worker(a, findings_dict, index):
a.analyze()
findings_dict[index] = a.findings
with Manager() as manager:
findings = manager.dict()
threads = []
for i, ticket in enumerate(tickets):
a = JiraAnalyze(pipeline, jira, ticket)
analyzers.append(a)
t = Process(target=worker, args=(a, findings, i))
t.start()
threads.append(t)
for t in threads:
t.join()
for i, a in enumerate(analyzers):
a.findings = findings[i]
a.present()
Möchtest du Threads oder Prozesse verwenden? Dann kann ich dir das entsprechende Setup bauen.
Matti
2025-04-18, 20:59:05
Threads nutzen leider nichts, weil mehrere Threads in Python auch nur 1 CPU-Kern benutzen. Habe mich für ChatGPT's Lösung mit multiprocessing.Manager entschieden.
vBulletin®, Copyright ©2000-2025, Jelsoft Enterprises Ltd.