[PYTHON] Tiefer über Unterprozess (3 Serien, aktualisierte Version)

Einführung

Artikel aus dem Jahr 2017 basiert auf zwei Systemen, und ich dachte, es wäre besser, die schlampigen Informationen zu aktualisieren, und als Ergebnis begann ich mit der Bearbeitung. Dieser Artikel wurde neu erstellt, da anscheinend eine große Anzahl von Ergänzungen wie "subprocess.run ()" erforderlich sein würde.

Während wir die Unterprozessfunktion von früher erläutern (die Unterstützung wurde nicht beendet), werden wir sie synonym mit "subprocess.run ()" und "subprocess.Popen ()" beschreiben. Darüber hinaus werden wir mit diesen eine größere Vielfalt von Beschreibungen aufnehmen.

Wenn Sie es eilig haben, gibt es kein Problem, wenn Sie die allgemeinen Regeln von cmd description und run () und höher lesen.

Die Geschichte dessen, was das Modul überhaupt macht, ist Offiziell oder [Dieser Artikel](https://qiita.com/ Bitte beziehen Sie sich auf caprest / items / 0245a16825789b0263ad).

Was ist die Schlussfolgerung? ** Überlassen wir alles so weit wie möglich subprocess.run (). Wenn eine kompliziertere Verarbeitung erforderlich ist, verwenden Sie "subprocess.Popen ()", das auch die Grundlage für "subprocess.run ()" bildet. ** Soweit ich das beurteilen kann, sind keine weiteren in diesem Artikel vorgestellten Funktionen erforderlich (alle können ersetzt werden).

Modul verwendet


import io
import os
import time
import subprocess

Experimentelle Datei

hello.py


print('Hello world!')

Alte Ausführungsmethode für Shell-Befehle

Ich habe keine Chance mehr, es zu verwenden, aber ich werde es zusammenfassen, weil es beim Ausgraben von altem Code hilfreich ist.

os.system()

os.system (Befehl) (Offiziell) Führen Sie den Befehl (String) in der Subshell aus. Diese Funktion wird mit dem Standard-C-Funktionssystem () implementiert und unterliegt den gleichen Einschränkungen wie system (). Änderungen an sys.stdin usw. werden nicht in der Umgebung des ausgeführten Befehls berücksichtigt. (Weggelassen) Das Unterprozessmodul bietet leistungsstärkere Funktionen zum Ausführen neuer Prozesse und zum Abrufen von Ergebnissen. Es wird empfohlen, anstelle dieser Funktion das Unterprozessmodul zu verwenden.

os.system()Beispiel


#Das Ergebnis wird am Terminal ausgegeben
print(os.system('ls')) # 0

#Auf dem Terminal → sh: 1: tekito: not found
print(os.system('tekito')) #32512 (← umweltabhängig?Gibt eine andere Zahl als 0 zurück.)

os.spawn Funktionen (os.spawnl (Modus, Pfad, ...),os.spawnle (Modus, Pfad, ..., env),os.spawnlp (Modus, Datei,.). ..),os.spawnlpe (Modus, Datei, ..., env),os.spawnv (Modus, Pfad, Argumente),os.spawnve (Modus, Pfad, Argumente, env), os.spawnvp (Modus, Datei, Argumente), os.spawnvpe (Modus, Datei, Argumente, env)) ist ~~ Ich verstehe nicht ~~ Es scheint problematisch zu sein, wenn Sie es im Detail tun Es scheint eine Nuance wie "(Prozess) wird erstellt") zu haben.

os.popen()

os.popen (cmd, mode = 'r', buffering = -1) (Official) Öffnen Sie die Pipe-Ein- / Ausgabe zum oder vom Befehl cmd. Der Rückgabewert ist ein offenes Dateiobjekt, das mit der Pipe verbunden ist und gelesen oder geschrieben werden kann, je nachdem, ob der Modus 'r' (Standard) oder 'w' ist. (Weggelassen) Es wird mit subprocess.Popen implementiert. Weitere Informationen zum Verwalten und Kommunizieren mit Unterprozessen finden Sie in der Klassendokumentation.

os.popen()Beispiel


#Lesen Sie das Ausgabeergebnis
print(os.popen('ls h*.py','r').readlines())
'''
['hello.py\n', 'hello2.py\n']
'''

Allgemeine Regeln für die cmd-Beschreibung im Unterprozess

Geben Sie als Zeichenfolge → shell = True an ・ Störungsrisiko durch Angebote Geben Sie als Liste der Zeichenfolgen → shell = False (Standard) an ・ Geringer Freiheitsgrad, da keine Platzhalter verwendet werden können

(Offiziell) Wenn die Shell True ist, wird der angegebene Befehl von der Shell ausgeführt. Sie verwenden Python hauptsächlich für erweiterte Steuerungsabläufe (mehr als die meisten System-Shells) sowie für Shell-Pipes, Platzhalter für Dateinamen, die Erweiterung von Umgebungsvariablen und die Erweiterung Ihres Benutzer-Ausgangsverzeichnisses. Dies kann nützlich sein, wenn Sie einfachen Zugriff auf andere Shell-Funktionen wünschen. (Offiziell) Wenn Sie die Shell explizit mit "shell = True" aufrufen, liegt es in der Verantwortung der Anwendung, korrekte Anführungszeichen für alle Leerzeichen und Metazeichen sicherzustellen, um die Sicherheitsanfälligkeit durch Shell-Injektion zu beheben.

shell=Befehle, die nur mit True realisiert werden können


#So geben Sie eine Zeichenfolgenliste ein (die folgenden 5 sind mit dieser Notation nicht möglich)
print(subprocess.call(['ls','-l'], shell=False)) # 0

#Shell-Pipeline
print(subprocess.call('echo -e "a\nb\nc" | wc -l', shell=True)) # 0
#Semikolon
print(subprocess.call('echo Failed.; exit 1', shell=True)) # 1
#Platzhalter
print(subprocess.call('ls -l *.py', shell=True)) # 0
#Umgebungsvariable
print(subprocess.call('echo $HOME', shell=True)) # 0
#Tilda-Symbol für HOME
print(subprocess.call('ls -l ~', shell=True)) # 0

Funktionen vor der Integration von subprocess.run ()

Es gibt drei Arten, die unten gezeigt werden. Sie sind grob in die drei Elemente in der folgenden Tabelle eingeteilt. In beiden Fällen kann ON / OFF in "subprocess.run ()" umgeschaltet werden, so dass dies nicht mehr erforderlich ist.

Funktionsname Kündigungsstatus Ausgabeergebnis CalledProcessError
(.run()Argument / Attribut) .returncode .stdout check
subprocess.call()
subprocess.check_call()
subprocess.check_output()

subprocess.call()

subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False, cwd=None, timeout=None) Befehlsausführung. Der Rückgabewert ist der Endstatus (0 bedeutet normales Ende).

Hauptoptionen ① (Standardeingabe / -ausgabe, Zeitüberschreitung)

** (gemeinsam mit anderen Unterprozessfunktionen) **

Wenn Sie eine Datei für die Standardeingabe / -ausgabe angeben, geben Sie sie in "open ()" ein. Es ist fast beiseite, aber in der Python3-Serie gibt es fast kein Problem, wenn Sie den Bytetyp (mode = 'rb' / 'wb') anstelle des str-Typs ( mode =' r '/' w') (mode = 'rb' / 'wb') auswählen. Wie Sie anhand der Untersuchung sehen können, werden beide unterstützt, oder in vielen Fällen wird nur der Bytetyp unterstützt.

Verwendungsbeispiele für Schlüsseloptionen


print(subprocess.call(['cat', 'hello.py'])) # 0
#Geben Sie die Standardeingabe / Standardausgabe an (die zweite ist hallo2.py wird erstellt)
print(subprocess.call(['cat'], stdin=open('hello.py','rb'))) # 0
print(subprocess.call(['cat', 'hello.py'], stdout=open('hello2.py','wb'))) # 0

#Zeitlimit angeben
print(subprocess.call(['sleep', '3'], timeout=1)) # TimeoutExpired

#(Ergänzung) Auch mit der Option cwd, die das Ausführungsverzeichnis angibt~Wird nicht unterstützt.
print(subprocess.call(['ls','-l'], shell=False, cwd = "~")) # FileNotFoundError

subprocess.check_call()

subprocess.check_call(args, *, stdin=None, stdout=None, stderr=None, shell=False, cwd=None, timeout=None) Befehlsausführung. Der Rückgabewert ist der Endstatus (0 bedeutet normales Ende). Gibt CalledProcessError bei abnormaler Beendigung zurück.

check_call()Anwendungsbeispiel


#Erfolgreiche Fertigstellung
print(subprocess.call(['cat', 'hello.py'])) # 0
print(subprocess.check_call(['cat', 'hello.py'])) # 0

#Abnormale Beendigung: Gibt einen Ausnahmefehler anstelle eines Fehlerstatus zurück
print(subprocess.call(['cat', 'undefined.py'])) # 1
print(subprocess.check_call(['cat', 'undefined.py'])) # CalledProcessError

subprocess.check_output()

subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, cwd=None, encoding=None, errors=None, universal_newlines=None, timeout=None, text=None) Befehlsausführung. Der Rückgabewert ist die Standardausgabe.

(Offiziell) Standardmäßig gibt diese Funktion die Daten als codierte Bytes zurück.

Wenn es sich also um eine Zeichenfolge usw. handelt, wird sie dekodiert und dann verarbeitet.

check_output()Anwendungsbeispiel


o = subprocess.check_output('ls h*.py', shell=True)
print(o) # b'hello.py\nhello2.py\n'
print(o.decode().strip().split('\n')) # ['hello.py', 'hello2.py']
Hauptoption (2) (Standardfehlerausgabe, Sonderwert)

** (gemeinsam mit anderen Unterprozessfunktionen) **

Das Ausgabeziel kann durch Angabe von "stderr" geändert werden.

--subprocess.DEVNULL: Geben Sie das Standardeingabe- / Ausgabeziel als os.devnull an (Bit-Bucket, Schwarzes Loch). --subprocess.PIPE: Geben Sie die Pipe zum Standardeingabe- / Ausgabeziel an --subprocess.STDOUT: Geben Sie an, dass die Standardfehlerausgabe an dasselbe Handle wie die Standardausgabe ausgegeben wird (nur für 2> 1 & .stderr).

Standardoperationen im Zusammenhang mit der Fehlerausgabe


#Alle Ausgaben verwerfen
o = subprocess.call(['cat', 'undefined.py'], stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)

#Nehmen Sie die Standardausgabe heraus
try:
    o = subprocess.check_output(['cat', 'hello.py'])
    print(o) # b"print('Hello world!')"
except subprocess.CalledProcessError as e:
    print('ERROR:', e.output)

#Standardfehlerausgabe extrahieren
try:
    o = subprocess.check_output(['cat', 'undefined.py'], stderr=subprocess.PIPE)
    print(o)
except subprocess.CalledProcessError as e:
    print('ERROR:', e.stderr) # ERROR: b'cat: undefined.py: No such file or directory\n'

#Integrieren Sie Standardfehler in die Standardausgabe
try:
    o = subprocess.check_output(['cat', 'undefined.py'], stderr=subprocess.STDOUT)
    print(o)
except subprocess.CalledProcessError as e:
    # e.e statt stderr.Beachten Sie, dass es stdout ist. Darüber hinaus e.Ausgabe ist auch möglich.
    print('ERROR:', e.stdout) # ERROR: b'cat: undefined.py: No such file or directory\n'

Ersetzung durch subprocess.run ()

(Offiziell) Die empfohlene Methode zum Starten eines Unterprozesses ist die Verwendung der Funktion run (), die alle Verwendungen verarbeiten kann. Für eine erweiterte Verwendung können Sie auch die zugrunde liegende Popen-Oberfläche direkt verwenden.

Ersetzen Sie also den obigen Code durch "run ()". Siehe auch die obige Tabelle für angegebene Optionen.

subprocess.run()

subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, capture_output=False, shell=False, cwd=None, timeout=None, check=False, encoding=None, errors=None, text=None, env=None, universal_newlines=None)

Subprocess.call () ersetzen

Fügen Sie den Rückgabecode hinzu. Zusätzlich zu dem "stdin", das bei der Einführung von "subprocess.call ()" verwendet wird, gibt es eine Option namens "input". Dies ist eine Standardeingabespezifikation unter Verwendung von "subprocess.Popen (). Communicate ()", die später beschrieben wird und eine Zeichenfolge angibt.

run()Ersatz: Beispiel für die Verwendung der Schlüsseloption


print(subprocess.run('ls -l h*.py', shell=True).returncode) # 0
#Standard-Eingabe / Standard-Ausgabe angeben (hallo2).py wird erstellt)
print(subprocess.run(['cat'], stdin=open('hello.py','rb'), stdout=open('hello2.py','wb')).returncode) # 0
# (Eingabe verwenden. Fast gleichbedeutend mit oben)
print(subprocess.run(['cat'], input=open('hello.py','rb').read(), stdout=open('hello2.py','wb')).returncode) # 0

#Zeitlimit angeben
print(subprocess.run(['sleep', '3'], timeout=1).returncode) # TimeoutExpired
Subprocess.check_call () Ersatz

Fügen Sie check = True hinzu. Es gibt auch eine spätere Methode namens ".check_returncode ()".

run()Ersetzen: prüfen_call()Anwendungsbeispiel


#Erfolgsstatus
print(subprocess.run(['cat', 'hello.py']).returncode) # 0
print(subprocess.run(['cat', 'hello.py'], check=True).returncode) # 0

#Gibt einen Ausnahmefehler anstelle eines Fehlerstatus zurück
print(subprocess.run(['cat', 'undefined.py']).returncode) # 1
print(subprocess.run(['cat', 'undefined.py'], check=True).returncode) # CalledProcessError

#(Ergänzung) prüfen_returncode()Spätere Fehlerausgabe mit
p = subprocess.run(['cat', 'undefined.py'], check=False)
print(p.returncode) # 1
print(p.check_returncode()) # CalledProcessError
Subprocess.check_output () ersetzen

Verwenden Sie die Option "stdout" und ".stdout".

run()Ersetzen: prüfen_output()Anwendungsbeispiel


o = subprocess.run('ls h*.py', shell=True, stdout=subprocess.PIPE, check=True).stdout
print(o) # b'hello.py\nhello2.py\n'
print(o.decode().strip().split('\n')) # ['hello.py', 'hello2.py']

Mit der neuen optionalen Funktion haben die Standardoperationen im Zusammenhang mit der Fehlerausgabe mehr Freiheit bei der Verwendung von "run ()" als bei der Verwendung von "check_output ()".

Standardoperationen im Zusammenhang mit der Fehlerausgabe


# check=False (default)So können Sie in strerr schauen, ohne mit einem Fehler anzuhalten
o = subprocess.run(['cat', 'undefined.py'], check=False, capture_output=True)
print((o.stdout, o.stderr)) # (b'', b'cat: undefined.py: No such file or directory\n')

#Integrieren Sie die Standardfehlerausgabe in die Standardausgabe.
o = subprocess.run(['cat', 'undefined.py'], check=False, stderr=subprocess.STDOUT, stdout=subprocess.PIPE)
print(o.stdout) # b'cat: undefined.py: No such file or directory\n'

# capture_output=Wenn True, wird PIPE sowohl für die Standardausgabe als auch für die Standardfehlerausgabe angegeben.
try:
    o = subprocess.run(['cat', 'undefined.py'], check=True, capture_output=True)
    print(o.stdout)
except subprocess.CalledProcessError as e:
    print('ERROR:',e.stderr) # ERROR: b'cat: undefined.py: No such file or directory\n'

Hochflexible Verarbeitung durch Subprozess.Popen ()

Offiziell Innerhalb dieses Moduls wird die zugrunde liegende Prozesserstellung und -verwaltung von der Popen-Klasse verwaltet. Die Popen-Klasse bietet viel Flexibilität, sodass Entwickler weniger häufige Fälle behandeln können, die nicht durch einfache Funktionen abgedeckt werden.

Also eine Einführung in die Flexibilität. Insbesondere werden wir uns auf Dinge konzentrieren, die mit run () nicht reproduziert werden können. Als Hauptfunktion erstellt subprocess.Popen () nur einen Prozess ** und wartet nicht auf das Ende **. Verwenden Sie .poll (), um das Ende zu bestätigen und um nach Bestätigung des Endes fortzufahren. Führen Sie .wait () aus.

Ersatzbeispiel (call ())

** Viele Argumente und Attribute von "Popen ()" sind für "run ()" gleich. ** ** ** Um "subprocess.call ()" zu reproduzieren, verwenden Sie ".return code", der auch in "subprocess.run ()" verwendet wurde. Wenn Sie anderen Code reproduzieren, kann dies auf die gleiche Weise erfolgen wie bei run ().

Popen()Ersetzen: anrufen()Anwendungsbeispiel


#Geben Sie die Standardeingabe / Standardausgabe an (die zweite ist hallo2.py wird erstellt)
p = subprocess.Popen('ls -l h*.py', shell=True)
p.wait()
print(p.returncode) # 0

#Standard-Eingabe / Standard-Ausgabe angeben (hallo2).py wird erstellt)
p = subprocess.Popen(['cat'], stdin=open('hello.py','rb'), stdout=open('hello2.py','wb'))
p.wait()
print(p.returncode) # 0

#Zeitlimit angeben
p = subprocess.Popen(['sleep', '3'])
p.wait(timeout=1) # TimeoutExpired

Deadlock und Popen.communicate ()

Popen.communicate () ist eine Methode, die ein Taple in Form von (Standardausgabe, Standardfehlerausgabe) zurückgibt (ggf. mit einer Zeichenketteneingabe).

(Offiziell) Mit Prozess kommunizieren: Daten an Standardeingabe senden. Lesen Sie Daten von stdout und stderr, bis das Ende der Datei erreicht ist. Warten Sie, bis der Vorgang abgeschlossen ist. (Ausgelassen) communic () gibt ein Taple zurück (stdout_data, stderr_data). (Offiziell) Warnung Mit .stdin.write, .stdout.read kann .stderr.read den OS-Pipe-Puffer einer anderen Pipe füllen und einen Deadlock verursachen. Verwenden Sie communic (), um dies zu vermeiden.

[Dieser Artikel](https://qiita.com/caprest/items/0245a16825789b0263ad#%E3%83%91%E3%82%A4%E3%83%97%E3%81%AB%E3%81%A4% E3% 81% 84% E3% 81% A6) gibt ebenfalls eine ausführliche Erklärung. Wenn das Risiko besteht, dass sich die Eingabe- / Ausgabedaten zu stark im Puffer ansammeln, verwenden Sie "communic ()", das alles auf einmal verwaltet. Es gibt auch eine Person, die tatsächlich mit communic () auf einen Deadlock reagiert hat (article).

Der Nachteil ist, dass ** es unmöglich wird, Ein- und Ausgänge innerhalb eines Prozesses mehrmals auszutauschen **. Es kann nicht zusammen mit "communic ()" für das unten beschriebene Echtzeit-Ausgabemanagement und die interaktive Verarbeitung verwendet werden.

Ein weiterer Unterschied besteht darin, dass die für die Timeout-Verarbeitung erforderliche Option "Timeout" nicht in "Popen (). Strout" usw. vorhanden ist, sondern in "communic ()". Hierfür gibt es eine Lösung, wie in [diesem Artikel] vorgestellt (https://qiita.com/toshitanian/items/133b42355b7867f5c458).

Reproduktion der Shell-Pipeline

Es wird auch in Official eingeführt. Sie können es als Zeichenfolge als "shell = True" angeben, aber Sie können es mit einer Grammatik reproduzieren, die es wie unten gezeigt vermeidet. Weitere Informationen zu SIGPIPE auf dem Weg finden Sie unter hier oder hier. / 39190250 / unter welcher Bedingung-macht-ein-Python-Unterprozess-ein-Sigpipe).

Popen()Beispiel: Shell-Pipeline


p1 = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE) #Pipe zum Ausgabeziel
p2 = subprocess.Popen(['grep', 'python'], stdin=p1.stdout, stdout=subprocess.PIPE) #Empfange p1 zur Eingabe
p1.stdout.close() # Allow p1 to receive a SIGPIPE if p2 exits.
print(p2.communicate()[0].decode().strip().split('\n')) #stdout bekommen

Statusbestätigung und Echtzeit-Ausgabeverwaltung durch .poll ()

Ich erwähnte, dass "Popen ()" nicht auf das Ende wartet, aber Sie können mit ".poll ()" überprüfen, ob es sich im Endzustand befindet. Wenn es nicht fertig ist, gibt es None zurück, und wenn es fertig ist, wird sein Status zurückgegeben. Sie können die Ausgabe zeilenweise mit .stdout.readline () abrufen. Dies kann ** jedes Mal erreicht werden, wenn die Ausgabe in Echtzeit unterbrochen wird **. Wenn Sie dagegen eine Methode wie ".stdout.read ()" verwenden, die alle Ausgaben auf einmal erfasst, wechselt sie automatisch in den Endwartezustand **.

Popen()Beispiel: Echtzeit-Ausgabeverwaltung


cmd = 'echo Start;sleep 0.5;echo 1;sleep 0.5;echo 2;sleep 0.5;echo 3;sleep 0.5;echo Finished'
p = subprocess.Popen(cmd, shell=True, stderr=subprocess.STDOUT, stdout=subprocess.PIPE)
#Holen Sie sich in Echtzeit
while p.poll() is None:
    print('status:',p.poll(), p.stdout.readline().decode().strip())
print('status:',p.poll())
print()

p = subprocess.Popen(cmd, shell=True, stderr=subprocess.STDOUT, stdout=subprocess.PIPE)
#Keine Ausgabe nach 2 Sekunden
print('status:',p.poll(), p.stdout.read().decode().strip())
'''
status: None Start
status: None 1
status: None 2
status: None 3
status: None Finished
status: 0

status: None Start
1
2
3
Finished
'''

In diesem Artikel wird ein besseres Modell des Echtzeit-Ausgabeverwaltungscodes vorgestellt.

Interaktiver Ein- / Ausgang

Der Austausch des mehrmaligen Sendens der Eingabe und des Erhaltens der Ausgabe jedes Mal wird wie folgt realisiert. Ich habe auf [diesen Artikel] verwiesen (https://kae315.hatenablog.com/entry/20110519/1305807239). Da es nicht durch "communic ()" reproduziert werden kann, wodurch die Eingabe und Ausgabe von Daten sofort abgeschlossen wird, besteht die Gefahr eines Deadlocks, wenn ein großer Datenaustausch erforderlich ist.

Erstellen Sie zunächst als Vorbereitung einen Python-Code, der mehrere Eingaben erfordert und jedes Mal eine Ausgabe generiert.

(Vorbereitung) calc.py


a = int(input())
print('n    =', a)
b = int(input())
print(' + {} ='.format(b), a+b)
c = int(input())
print(' - {} ='.format(c), a-c)
d = int(input())
print(' * {} ='.format(d), a*d)
e = int(input())
print(' / {} ='.format(e), a/e)

Gehen Sie dazu wie folgt vor. Beachten Sie, dass, wenn Sie nicht spülen, der Zustand im Puffer gespeichert und nicht eingegeben wird.

Popen()Beispiel: Interaktiver Ein- / Ausgang


numbers = range(1, 6)

#Nicht interaktiv (kommunizieren)()Senden Sie alles auf einmal mit
p = subprocess.Popen(['python', 'calc.py'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
#Mit Zeilenvorschubcode verketten
str_nums = '\n'.join(map(str, numbers))
o, e = p.communicate(input=str_nums.encode())
print(o.decode())

'''
n    = 1
 + 2 = 3
 - 3 = -2
 * 4 = 4
 / 5 = 0.2
'''

#Interaktiv (.stdin.write()Senden Sie Zeile für Zeile mit
p = subprocess.Popen(['python', 'calc.py'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
for n in numbers:
    #Zahlen senden
    p.stdin.write(str(n).encode())
    #Zeilenumbruch senden (Eingabe()Erforderlich, da es sich um eine Eingabe handelt für)
    p.stdin.write('\n'.encode())
    #Geben Sie den Puffer frei (wichtig)
    p.stdin.flush()
    #Lesen Sie das Ergebnis in einer Zeile (verwenden Sie die while-Anweisung, wenn sie mehrere Zeilen umfasst).
    print(p.stdout.readline().decode().strip())

'''
n    = 1
 + 2 = 3
 - 3 = -2
 * 4 = 4
 / 5 = 0.2
'''

Parallele Ausführung (Informationsmangel)

Da "Popen ()" nicht auf das Ende wartet, können mehrere Prozesse gleichzeitig ausgeführt werden. Die asynchrone Verarbeitung wird vom Modul "asyncio" verwaltet, einige von ihnen entsprechen jedoch dem "Unterprozess" (Official. asyncio-subprocess.html # asyncio-subprocess)). Darüber hinaus gibt es verschiedene asynchrone Prozesse wie diesen Artikel und diesen Artikel. Es gibt viele Artikel. Ich denke, dass es notwendig ist, "** was ist die geringste Verzögerung und das geringste Risiko **" zu erfassen, wenn zwischen verschiedenen Methoden ausgewählt wird, aber da ich derzeit nicht so viel Wissen habe, ist dies hier. Die obige Diskussion wird weggelassen. Das Folgende ist vorerst eine vereinfachte Version.

Parallele Ausführung


#Permutation
print('start')
s = time.time()
running_procs = [
    subprocess.run(['sleep', '3']),
    subprocess.run(['sleep', '2']),
    subprocess.run(['sleep', '1']),
    ]
# run()In diesem Fall dauert es insgesamt etwa 6 Sekunden, bis die Ausführung in der richtigen Reihenfolge erfolgt ist
print('finish [run()]', time.time() - s)
# ----------------------------
#Parallel
print('start')
s = time.time()
procs = [
    subprocess.Popen(['sleep', '3']),
    subprocess.Popen(['sleep', '2']),
    subprocess.Popen(['sleep', '1']),
    ]
# Popen()Wenn Sie dann gerade erst anfangen, endet es sofort
print('finish [run Popen()]', time.time() - s)

#Warten, bis jeder Prozess abgeschlossen ist
[p.wait() for p in procs]
#Die Verarbeitung ist in ca. 3 Sekunden abgeschlossen, was dem längsten Vorgang entspricht
print('finish [wait Popen()]', time.time() - s)

Am Ende

Es ist ersichtlich, dass die meisten der verschiedenen Prozesse sofort mit "run ()" ausgeführt werden können und dass eine weitaus flexiblere Anwendung, die asynchron und interaktiv ist, durch die vollständige Verwendung von "Popen ()" möglich ist.

Recommended Posts

Tiefer über Unterprozess (3 Serien, aktualisierte Version)
Ein Hinweis zum Unterprozess