Python Multiprocessing mit Rückgabewert

1Justin

Cadet 4th Year
Registriert
März 2021
Beiträge
89
Hallo!
Ich versuche mich gerade in Python in das Thema "Multiprocessing" einzuarbeiten.
Im Internet habe ich folgendes (für mich noch verständliches) Code-Beispiel gefunden:

Code:
import multiprocessing
import time

def task():
    print('Sleeping for 0.5 seconds')
    time.sleep(0.5)
    print('Finished sleeping')
    return "Deutschland"

if __name__ == "__main__":
    start_time = time.perf_counter()

    # Creates two processes
    p1 = multiprocessing.Process(target=task)
    p2 = multiprocessing.Process(target=task)

    # Starts both processes
    p1.start()
    p2.start()

    finish_time = time.perf_counter()

    print(f"Program finished in {finish_time-start_time} seconds")


Frage an die Experten:
Wie komme ich an den Rückgabewert (in meinem Bespiel "Deutschland") heran?
Der Rückgabewert kann übrigens auch ein Dictionary sein!

Im Internet habe ich gelesen, man müsse "Queues" einbauen. Die Codeschnipsel sind mir dann aber doch zu komplex.
Kann man den obigen Code nicht um ein paar wenige Zeilen erweitern, damit ich an den Rückgabewert herankomme?
 
In deinem Fall würde ich dir empfehlen mit multiprocessing Pool zu arbeiten. Das ist wesentlich übersichtlicher für deine Zwecke.
 
Oder concurrent.futures:

Python:
from concurrent.futures import ThreadPoolExecutor, wait
import time

def task(country):
    print(f"Sleeping for 0.5 seconds in {country}")
    time.sleep(0.5)
    print(f"Finished sleeping in {country}")
    return country

if __name__ == "__main__":
    start_time = time.perf_counter()
    countries = ["Deutschland", "Frankreich", "Spanien"]
    futures = []
    
    with ThreadPoolExecutor(max_workers=4) as executor:
        for country in countries:
            futures.append(executor.submit(task, country))

    wait(futures)

    for future in futures:
        print(future.result())

    finish_time = time.perf_counter()
    
    print(f"Execution took {round(finish_time - start_time, 1)}s")
 
Zuletzt bearbeitet:
1Justin schrieb:
Wie komme ich an den Rückgabewert (in meinem Bespiel "Deutschland") heran?
dein task() ist ein eigenständiger prozess, der nichts mit return zurückgeben kann. der hat maximal einen exit-code. es gibt mehrere wege, wie man daten aus einem prozess ins hauptprogramm bekommt - siehe z.b. dieser thread auf stackoverflow. multiprocessing.Pool sieht doch hübsch kompakt aus :)
 
0x8100 schrieb:
dein task() ist ein eigenständiger prozess, der nichts mit return zurückgeben kann. der hat maximal einen exit-code. es gibt mehrere wege, wie man daten aus einem prozess ins hauptprogramm bekommt - siehe z.b. dieser thread auf stackoverflow. multiprocessing.Pool sieht doch hübsch kompakt aus :)
Sorry, einen ersten Test konnte ich erst jetzt durchführen:

Code:
import multiprocessing

meineListe = ["Apfel", "Birne", "Banane"]

class MeineKlasse():
    def auto(variable):
        satz = "Eine Obstsorte: " + variable
        print(satz)
        return satz

if __name__ == '__main__':
    pool = multiprocessing.Pool(processes=3)
    print(pool.map(MeineKlasse.auto, meineListe))

Als Ergebnis bekomme ich zurückgeliefert:

Eine Obstsorte: Apfel
Eine Obstsorte: Birne
Eine Obstsorte: Banane
['Eine Obstsorte: Apfel', 'Eine Obstsorte: Birne', 'Eine Obstsorte: Banane']


D.h. pool.map zerlegt die Liste (lt. Doku sind nur Listen zulässig - warum eigentlich?), und ruft - je nach Länge der Liste - die Funktion/Methode "MeineKlasse.auto" mehrmals auf.
Das ist aber gar nicht mein Ziel, stattdessen soll MeineKlasse.auto immer nur 1mal aufgerufen werden, jedoch möchte ich der Funktion schon mehrere Parameter übergeben. Geht das?

Meine Klassen/Methoden beinhalten Vererbungen, und verlangen immer mehrere Parameter:
Code:
class MeineKlasse2(VererbungMeineKlasse1):
    def __init__(self, parameter1, parameter2, parameter3, parameter4):

Wie kann ich nun MeineKlasse2 in einem eigenen Prozess aufrufen, so dass die Klasse bzw. das Objekt nur 1mal ausgeführt wird, ich jedoch trotzdem alle 4 Parameter übergeben kann?
 
1Justin schrieb:
D.h. pool.map zerlegt die Liste und ruft - je nach Länge der Liste - die Funktion/Methode "MeineKlasse.auto" mehrmals auf.
das ist doch der sinn von mulitprocessing - jedes element deiner input-liste wird parallel abgearbeitet. willst du mehrere parameter pro prozess übergeben, musst du eben deine liste anders gestalten, z.b.
Python:
import multiprocessing

meineListe = [["Apfel", "Birne", "Banane"], ["foo", "bar", "baz"]]

class MeineKlasse():
    def auto(variable):
        satz = f"Obstsorten: {', '.join(variable)}"
        print(satz)
        return satz

if __name__ == '__main__':
    pool = multiprocessing.Pool(processes=3)
    print(pool.map(MeineKlasse.auto, meineListe))

Code:
Obstsorten: Apfel, Birne, Banane
Obstsorten: foo, bar, baz
['Obstsorten: Apfel, Birne, Banane', 'Obstsorten: foo, bar, baz']
 
Zurück
Oben