check_call()
powraca po zakończeniu procesu /bin/sh
bez czekania na proces potomka.
check_output()
czeka, aż wszystkie dane wyjściowe zostaną odczytane. Jeśli ssh
odziedziczy rurę, to check_output()
będzie czekał aż się zakończy (dopóki nie zamknie odziedziczonych końców rur). Przykładem
check_call()
Kod:
#!/usr/bin/env python
import subprocess
import sys
import time
start = time.time()
cmd = sys.executable + " -c 'import time; time.sleep(2)' &"
subprocess.check_call(cmd, shell=True)
assert (time.time() - start) < 1
Wyjście nie jest odczytywany; check_call()
zwraca natychmiast, nie czekając na proces python w tle wnuka.
check_call()
to tylko Popen().wait()
. Popen()
uruchamia proces zewnętrzny i natychmiast wraca, nie czekając na jego zakończenie. .wait()
zbiera status wyjścia dla procesu - nie czeka na inne procesy (wnuki).
Jeśli wyjście jest odczytywany (to jest przekierowywany i proces wnuk dziedziczy pyton rurę stdout):
start = time.time()
subprocess.check_output(cmd, shell=True)
assert (time.time() - start) > 2
następnie czeka, aż proces Pythona w tle, który odziedziczył wyloty rur.
check_output()
dzwoni Popen().communicate()
, aby uzyskać dane wyjściowe. .communicate()
dzwoni .wait()
wewnętrznie tj.również czeka na wyjście powłoki i check_output()
czeka na EOF.
Jeśli wnuczek nie dziedziczy rurę następnie check_output()
nie czeka na niego:
start = time.time()
cmd = sys.executable + " -c 'import time; time.sleep(2)' >/dev/null &"
subprocess.check_output(cmd, shell=True)
assert (time.time() - start) < 1
wyjście wnuczek jest przekierowany do /dev/null
znaczy, że nie dziedziczy rurę rodzica i dlatego check_output()
może wyjść nie czekając na to.
Uwaga: &
na końcu, który umieszcza proces pythona wnuka w tle. Nie działa w systemie Windows, w którym domyślnie shell=True
domyślnie zaczyna się cmd.exe
.
Świetne wyjaśnienie. –