Punkte, bei denen bei der Verwendung von Lambda während der Python-Schleifenverarbeitung leicht Fehler auftreten können

Ich habe den folgenden Code geschrieben, um "500 Dateien parallel herunterzuladen" in Python.

from time import sleep
from concurrent.futures import ThreadPoolExecutor

def func(i):
    #Eigentlich Datei-Download-Prozess
    sleep(1)
    print(f"{i}\n", flush=True, end="")

with ThreadPoolExecutor(max_workers=3) as executor:
    for i in range(500):
        # 0~Laden Sie die Datei 499 parallel herunter
        executor.submit(
            lambda: func(i)
        )

Als ich dies ausführte, war das Verhalten wie folgt: "Die Verarbeitung wird viele Male mit derselben Nummer ausgeführt".

499
499
499
499
499
499
144
145
146
1
0
2
(Unten weggelassen)

Anscheinend "wird der Wert von" i "gelesen, wenn func tatsächlich ausgeführt wird, so viele Werte von" i "am Ende der Schleife werden gelesen."

Wenn Sie "functools.partial" wie unten gezeigt verwenden, wird es wie ursprünglich erwartet ausgeführt: "Führen Sie die Verarbeitung mit allen Werten von" i "von 0 bis 499 durch".

from time import sleep
from functools import partial
from concurrent.futures import ThreadPoolExecutor

def func(i):
    sleep(1)
    print(f"{i}\n", flush=True, end="")

with ThreadPoolExecutor(max_workers=3) as executor:
    for i in range(500):
        executor.submit(
            partial(func, i)
        )

Die Ausgabe sieht so aus.

0
2
1
3
5
4
6
7
8
9
10
11
12
13
14
(Unten weggelassen)

Wie ich aus diesem Blog erfahren habe, ist dies auch das Standardargument von Python Es scheint einen Weg zu geben, sich zu binden. Ich denke, es ist einfacher, die Absicht des Programms mit "partiell" zu vermitteln, aber es ist sicherlich interessant.

from time import sleep
from concurrent.futures import ThreadPoolExecutor

def func(i):
    sleep(1)
    print(f"{i}\n", flush=True, end="")

with ThreadPoolExecutor(max_workers=3) as executor:
    for i in range(500):
        executor.submit(
            lambda x=i: func(x)
        )

Nachtrag

Von einem Freund " submit erhält das Argument der auszuführenden Funktion Aber dann Ich bekam einen Tsukkomi, der sagte: "Ist es nutzlos?", Aber ich denke, das ist genau der Fall. Hier ist der Code für den tatsächlichen Gebrauch.

with ThreadPoolExecutor(max_workers=3) as executor:
    for i in range(500):
        executor.submit(func, i)

Recommended Posts

Punkte, bei denen bei der Verwendung von Lambda während der Python-Schleifenverarbeitung leicht Fehler auftreten können
Python-Listeneinschlussnotation, die leicht zu vergessen ist
Fünf nützliche Python-Datentypen, die leicht zu vergessen sind
Periodische Ausführungsverarbeitung bei Verwendung von tkinter [Python3]
10 Python-Fehler, die Anfängern häufig sind
Verwendung mehrerer Argumente bei der Parallelverarbeitung mithilfe der Mehrfachverarbeitung in Python
Was verwenden Sie beim Testen mit Python?
[LPIC 101] Ich habe versucht, die Befehlsoptionen zusammenzufassen, die leicht zu Fehlern führen können
Eine kleine Geschichte, die beim Schreiben von Twilio-Anwendungen mit Python auf AWS Lambda süchtig macht
Fehler aufgrund eines Konflikts zwischen Pythons bei der Verwendung von Gurobi
Einfache Möglichkeit, mit Google Colab mit Python zu kratzen
Überprüfen Sie types_map, wenn Sie Mimetypen mit AWS Lambda (Python) verwenden.
So erstellen Sie ein Python-Paket mit VS Code
[Einführung in Python] Wie stoppe ich die Schleife mit break?
Dinge, die Sie bei der Verarbeitung von Zeichenfolgen in Python2 beachten sollten
Wovon ich süchtig war, als ich Python Tornado benutzte
Dinge, die Sie bei der Verarbeitung von Zeichenfolgen in Python 3 beachten sollten
Python-Fehlermeldungen sind spezifisch und leicht zu verstehen "ga" (davor Doppelpunkt (:) und Semikolon (;))
Eine Geschichte, die es einfach macht, den Wohnbereich mit Elasticsearch und Python abzuschätzen