Pobieranie danych wyjściowych podprocesu.call () [duplicate]

To pytanie ma już odpowiedź tutaj:

W Jaki Sposób Mogę uzyskać wynik uruchomienia procesu za pomocą subprocess.call()?

Przekazanie obiektu StringIO.StringIO do stdout daje ten błąd:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/subprocess.py", line 444, in call
    return Popen(*popenargs, **kwargs).wait()
  File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/subprocess.py", line 588, in __init__
    errread, errwrite) = self._get_handles(stdin, stdout, stderr)
  File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/subprocess.py", line 945, in _get_handles
    c2pwrite = stdout.fileno()
AttributeError: StringIO instance has no attribute 'fileno'
>>> 
Author: Mooncrater, 2010-01-04

7 answers

Wyjście z subprocess.call() powinno być przekierowane tylko do plików.

Zamiast tego powinieneś użyć subprocess.Popen(). Następnie możesz przekazać subprocess.PIPE dla parametrów stderr, stdout i/lub stdin i odczytać z rur za pomocą metody communicate():

from subprocess import Popen, PIPE

p = Popen(['program', 'arg1'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
output, err = p.communicate(b"input data that is passed to subprocess' stdin")
rc = p.returncode

Rozumowanie jest takie, że obiekt podobny do pliku używany przez subprocess.call() musi mieć prawdziwy deskryptor pliku, a tym samym zaimplementować metodę fileno(). Samo użycie dowolnego obiektu podobnego do pliku nie załatwi sprawy.

Zobacztutaj aby uzyskać więcej informacji.

 156
Author: Mike,
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
2014-05-06 12:33:11

Jeśli masz wersję Pythona > = 2.7, możesz użyć podprocesu .check_output , który w zasadzie robi dokładnie to, co chcesz (zwraca standardowe wyjście jako string).

Prosty przykład (wersja Linuksa, patrz uwaga):

import subprocess

print subprocess.check_output(["ping", "-c", "1", "8.8.8.8"])

Zauważ, że polecenie ping używa notacji linuksowej (-c dla count). Jeśli spróbujesz tego w systemie Windows, pamiętaj, aby zmienić go na -n dla tego samego wyniku.

Jak skomentowano poniżej, bardziej szczegółowe wyjaśnienie znajdziesz w tej drugiej odpowiedzi .

 200
Author: sargue,
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
2018-03-08 07:40:18

Mam następujące rozwiązanie. Przechwytuje kod wyjścia, stdout i stderr wykonanego zewnętrznego polecenia:

import shlex
from subprocess import Popen, PIPE

def get_exitcode_stdout_stderr(cmd):
    """
    Execute the external command and get its exitcode, stdout and stderr.
    """
    args = shlex.split(cmd)

    proc = Popen(args, stdout=PIPE, stderr=PIPE)
    out, err = proc.communicate()
    exitcode = proc.returncode
    #
    return exitcode, out, err

cmd = "..."  # arbitrary external command, e.g. "python mytest.py"
exitcode, out, err = get_exitcode_stdout_stderr(cmd)

Mam również wpis na blogu tutaj .

Edit: rozwiązanie zostało zaktualizowane do nowszego, które nie wymaga pisania do temp. pliki.

 43
Author: Jabba,
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
2014-01-10 09:57:36

W Pythonie 3.5 + zaleca się użycie funkcji run z modułu podprocesu . Zwraca obiekt CompletedProcess, z którego można łatwo uzyskać zarówno wyjście, jak i Kod powrotu.

from subprocess import PIPE, run

command = ['echo', 'hello']
result = run(command, stdout=PIPE, stderr=PIPE, universal_newlines=True)
print(result.returncode, result.stdout, result.stderr)
 29
Author: Chiel ten Brinke,
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
2016-01-21 17:13:40

Niedawno wymyśliłem, jak to zrobić, a oto przykładowy kod z mojego obecnego projektu:

#Getting the random picture.
#First find all pictures:
import shlex, subprocess
cmd = 'find ../Pictures/ -regex ".*\(JPG\|NEF\|jpg\)" '
#cmd = raw_input("shell:")
args = shlex.split(cmd)
output,error = subprocess.Popen(args,stdout = subprocess.PIPE, stderr= subprocess.PIPE).communicate()
#Another way to get output
#output = subprocess.Popen(args,stdout = subprocess.PIPE).stdout
ber = raw_input("search complete, display results?")
print output
#... and on to the selection process ...

Teraz masz wyjście polecenia zapisane w zmiennej "output". "stdout = subprocess.PIPE "mówi klasie, aby utworzyła obiekt pliku o nazwie 'stdout' z wewnątrz Popen. Metoda communicate (), z tego co wiem, działa jako wygodny sposób na zwrócenie krotki wyjścia i błędów z uruchomionego procesu. Również Proces jest uruchamiany, gdy tworzy Popen.

 27
Author: Cheesemold,
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
2011-02-07 22:13:28

W Ipython powłoce:

In [8]: import subprocess
In [9]: s=subprocess.check_output(["echo", "Hello World!"])
In [10]: s
Out[10]: 'Hello World!\n'
Na podstawie odpowiedzi sargue ' a. Kredyt dla sargue ' a.
 11
Author: jhegedus,
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
2015-09-05 13:14:48

Poniższa lista przechwytuje stdout i stderr procesu w jednej zmiennej. Jest kompatybilny z Pythonem 2 i 3:

from subprocess import check_output

command = ["ls", "-l"]
try:
    output = check_output(command, stderr=STDOUT).decode()
    success = True 
except CalledProcessError as e:
    output = e.output.decode()
    success = False

Jeśli Twoje polecenie jest ciągiem znaków, a nie tablicą, przedrostek:

import shlex
command = shlex.split(command)
 5
Author: Zags,
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-11-17 17:53:24