Frage Pipe-Subprozess-Standardausgabe an eine Variable


Ich möchte einen Befehl ausführen pythongVerwenden Sie das Unterprozessmodul, und speichern Sie die Ausgabe in einer Variablen. Ich möchte jedoch nicht, dass die Ausgabe des Befehls auf dem Terminal gedruckt wird. Für diesen Code:

def storels():
   a = subprocess.Popen("ls",shell=True)
storels()

Ich bekomme die Verzeichnisliste im Terminal, anstatt sie zu speichern a. Ich habe es auch versucht:

 def storels():
       subprocess.Popen("ls > tmp",shell=True)
       a = open("./tmp")
       [Rest of Code]
 storels()

Dies gibt auch die Ausgabe von ls an mein Terminal aus. Ich habe diesen Befehl sogar mit der etwas veralteten os.system-Methode ausprobiert, seit ich renne ls > tmp im Terminal wird nicht gedruckt ls zum Terminal überhaupt, aber speichert es in tmp. Das Gleiche passiert jedoch.

Bearbeiten:

Ich erhalte den folgenden Fehler, nachdem ich dem Rat von Marcog gefolgt bin, aber nur wenn ich einen komplexeren Befehl ausführe. cdrecord --help. Python spuckt das aus:

Traceback (most recent call last):
  File "./install.py", line 52, in <module>
    burntrack2("hi")
  File "./install.py", line 46, in burntrack2
    a = subprocess.Popen("cdrecord --help",stdout = subprocess.PIPE)
  File "/usr/lib/python2.6/subprocess.py", line 633, in __init__
    errread, errwrite)
  File "/usr/lib/python2.6/subprocess.py", line 1139, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory

75
2017-12-22 23:45


Ursprung


Antworten:


Um die Ausgabe von zu erhalten ls, benutzen stdout=subprocess.PIPE.

>>> proc = subprocess.Popen('ls', stdout=subprocess.PIPE)
>>> output = proc.stdout.read()
>>> print output
bar
baz
foo

Der Befehl cdrecord --help Ausgaben zu stderr, also müssen Sie dieses indstead leiten. Sie sollten den Befehl auch in eine Liste von Tokens aufteilen, wie ich es unten getan habe, oder die Alternative besteht darin, den Befehl zu übergeben shell=True Argument, aber das feuert eine ausgewachsene Shell, die gefährlich sein kann, wenn Sie den Inhalt der Befehlszeichenfolge nicht steuern.

>>> proc = subprocess.Popen(['cdrecord', '--help'], stderr=subprocess.PIPE)
>>> output = proc.stderr.read()
>>> print output
Usage: wodim [options] track1...trackn
Options:
    -version    print version information and exit
    dev=target  SCSI target to use as CD/DVD-Recorder
    gracetime=# set the grace time before starting to write to #.
...

Wenn Sie einen Befehl haben, der sowohl an stdout als auch an stderr ausgegeben wird und Sie diese zusammenführen möchten, können Sie dies tun, indem Sie stderr in stdout einfügen und dann stdout abfangen.

subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

Wie erwähnt von Chris Morgansollten Sie verwenden proc.communicate() Anstatt von proc.read().

>>> proc = subprocess.Popen(['cdrecord', '--help'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> out, err = proc.communicate()
>>> print 'stdout:', out
stdout: 
>>> print 'stderr:', err
stderr:Usage: wodim [options] track1...trackn
Options:
    -version    print version information and exit
    dev=target  SCSI target to use as CD/DVD-Recorder
    gracetime=# set the grace time before starting to write to #.
...

112
2017-12-22 23:49



Wenn Sie Python 2.7 oder höher verwenden, ist der einfachste Weg, dies zu tun subprocess.check_output() Befehl. Hier ist ein Beispiel:

output = subprocess.check_output('ls')

Um auch stderr umzuleiten, können Sie folgendes verwenden:

output = subprocess.check_output('ls', stderr=subprocess.STDOUT)



Für den Fall, dass Sie Parameter an den Befehl übergeben möchten, können Sie entweder eine Liste verwenden oder eine Shell aufrufen und eine einzelne Zeichenfolge verwenden.

output = subprocess.check_output(['ls', '-a'])
output = subprocess.check_output('ls -a', shell=True)

23
2018-03-16 18:25



Mit a = subprocess.Popen("cdrecord --help",stdout = subprocess.PIPE) Sie müssen entweder eine Liste verwenden oder verwenden shell=True;

Eines davon wird funktionieren. Ersteres ist vorzuziehen.

a = subprocess.Popen(['cdrecord', '--help'], stdout=subprocess.PIPE)

a = subprocess.Popen('cdrecord --help', shell=True, stdout=subprocess.PIPE)

Auch, anstatt zu verwenden Popen.stdout.read/Popen.stderr.read, du solltest benutzen .communicate() (Informationen dazu finden Sie in der Unterprozessdokumentation).

proc = subprocess.Popen(['cdrecord', '--help'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = proc.communicate()

10
2017-12-23 00:17