Iterator in Blocks von mehreren items abfragen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Mick
User
Beiträge: 9
Registriert: Mittwoch 8. Januar 2020, 09:12

Hallo Leute,
vielen Dank für die Hilfe die letzten Tage. Ich hab leider schon wieder eine Frage.

Ich möchte einen Iterator in Blocks von mehreren items abfragen (z.B. 10000 items auf einmal). Der iterator ist sehr lang (mehrere Millionen items) und ich möchte die Blocks dann in einer Funktion bearbeiten und diese an den ProcessPoolExecutor weitergeben, um den Ablauf schneller zu machen.

Ich habe das ganze bisher als Verschachtelung von 3 loops gelöst: Außen eine while-loop, die bis zum Ende des iterators True bleibt, in der Mitte eine Loop für die Anzahl der parallelen Prozesse, die gestartet werden sollen und innen noch eine Loop für die Anzahl an items pro Prozess.

Code: Alles auswählen

iterator = iter(range(100))

bool_more_input = True

while bool_more_input:
	items_for_process = [[] for _ in range(4)] #Liste leeren
	for i in range(4): #Anzahl der Prozesse
		k=0
		while k < 10 and bool_more_input: #Anzahl items pro Prozess
			try:
				item = next(iterator)
				items_for_process[i].append(item)
				k += 1
			except StopIteration:
				bool_more_input = False

	print('Give items to ProcessPoolExecutor:')
	print(items_for_process)
Ich überlege, ob man das ganze irgendwie schöner lösen kann. Ich komme aber nicht drauf. Ich habe mit itertools.islice() herumprobiert, aber dann habe ich keine Rückmeldung mehr wann der iterator leer ist.
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

Naja, der Iterator ist fertig, wenn die Liste leer bleibt:

Code: Alles auswählen

while True:
    items_for_process = [list(islice(iterator, 1000)) for _ in range(4)]
    if not any(items_for_process):
        break
    print(items_for_process)
Benutzeravatar
__blackjack__
User
Beiträge: 14051
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Mick: So ein Executor hat eine `map()`-Methode und die hat ein `chunksize`-Argument. Ansonsten würde ich auch immer erst mal ins `more_itertools`-Modul schauen bevor ich etwas mit Iteratoren selbst erfinde.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Mick
User
Beiträge: 9
Registriert: Mittwoch 8. Januar 2020, 09:12

Sirius3 hat geschrieben: Freitag 10. Januar 2020, 10:46 Naja, der Iterator ist fertig, wenn die Liste leer bleibt:

Code: Alles auswählen

while True:
    items_for_process = [list(islice(iterator, 1000)) for _ in range(4)]
    if not any(items_for_process):
        break
    print(items_for_process)
Perfekt. Das ist viel schöner :)

more_itertools hab ich mir auch nochmal angeguckt und die haben tatsächlich "more_itertools.chunked(iterable, n)", um genau dieses Problem zu lösen. Danke euch!
Antworten