Podproces Pythona.wywołanie i podproces.Popen stdout
Więc zauważyłem subprocess.call
podczas gdy czeka na zakończenie polecenia przed kontynuacją skryptu Pythona, nie mam sposobu na uzyskanie stdout, z wyjątkiem subprocess.Popen
. Czy są jakieś alternatywne wywołania funkcji, które czekałyby na zakończenie? (Próbowałem też Popen.wait
)
UWAGA: staram się unikać os.system
połączenia
result = subprocess.Popen([commands...,
self.tmpfile.path()], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = result.communicate()
print out+"HIHIHI"
Moje wyjście:
HIHIHI
UWAGA: próbuję uruchomić wine
z tym.
4 answers
Używam poniższego konstruktu, chociaż możesz chcieć uniknąć shell=True
. Daje to wyjście i Komunikat o błędzie dla dowolnego polecenia, a także kod błędu:
process = subprocess.Popen(cmd, shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
# wait for the process to terminate
out, err = process.communicate()
errcode = process.returncode
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-15 13:22:20
subprocess.check_output(...)
Wywołuje proces, podnosi jeśli jego kod błędu jest niezerowy, a w przeciwnym razie zwraca jego stdout. To tylko krótki Skrót, więc nie musisz się martwić o PIPE
s I takie tam.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-15 13:31:25
Jeśli twój proces daje ogromne stdout i nie ma stderr, communicate()
może to być zły sposób, aby przejść z powodu ograniczeń pamięci.
Zamiast
process = subprocess.Popen(cmd, shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
# wait for the process to terminate
for line in process.stdout: do_something(line)
errcode = process.returncode
/ Align = "left" /
process.stdout
jest obiektem podobnym do pliku, który można traktować jako każdy inny tego typu obiekt, głównie:
- możesz
read()
z niego - możesz
readline()
z niego i - możesz to powtórzyć.
Ten ostatni jest tym, co robię powyżej, aby uzyskać jego zawartość linia po linii.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-29 09:35:10
Spróbowałbym czegoś takiego:
#!/usr/bin/python
from __future__ import print_function
import shlex
from subprocess import Popen, PIPE
def shlep(cmd):
'''shlex split and popen
'''
parsed_cmd = shlex.split(cmd)
## if parsed_cmd[0] not in approved_commands:
## raise ValueError, "Bad User! No output for you!"
proc = Popen(parsed_command, stdout=PIPE, stderr=PIPE)
out, err = proc.communicate()
return (proc.returncode, out, err)
... Innymi słowy niech shlex.split() wykonuje większość pracy. Nie próbowałbym analizować linii poleceń powłoki, znaleźć operatorów rur i skonfigurować własnego rurociągu. Jeśli masz zamiar to zrobić, będziesz musiał napisać kompletny parser składni powłoki i skończysz robiąc strasznie dużo hydrauliki.
Oczywiście nasuwa się pytanie, dlaczego po prostu nie użyć Popen z opcją shell=True (słowo kluczowe)? To będzie pozwala przekazać ciąg znaków (bez dzielenia ani parsowania) do powłoki i nadal zbierać wyniki do obsługi, jak chcesz. Mój przykład tutaj nie przetworzy żadnych potoków, backtików, przekierowań deskryptorów plików itp., które mogą być w poleceniu, wszystkie będą wyświetlane jako dosłowne argumenty polecenia. W ten sposób jest jeszcze bezpieczniejsze, gdy działa z shell = True ... Podałem głupi przykład sprawdzania polecenia w jakimś słowniku "zatwierdzonym poleceniem" lub ustawionym - - - przez to zrobiłoby bardziej sensowne jest znormalizowanie tego w ścieżkę bezwzględną, chyba że zamierzasz wymagać, aby argumenty zostały znormalizowane przed przekazaniem ciągu poleceń do tej funkcji.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-10 05:27:34