Äquivalent von Bash in Python Backticks
Frage
Was ist das Äquivalent der Backticks in Ruby und Perl in Python gefunden? Das heißt, in Ruby Ich kann dies tun:
foo = `cat /tmp/baz`
Was ist die äquivalente Aussage aussehen wie in Python? Ich habe versucht, os.system("cat /tmp/baz")
aber das bringt das Ergebnis auf Standard aus und kehrt zu mir den Fehlercode dieser Operation.
Lösung
output = os.popen('cat /tmp/baz').read()
Andere Tipps
Die flexibelste Art und Weise zu benutzen ist die subprocess
Modul:
import subprocess
out = subprocess.run(["cat", "/tmp/baz"], capture_output=True)
print("program output:", out)
capture_output
in Python 3.7 kann die Sonderfunktion check_output()
für ältere Versionen eingeführt wurde stattdessen verwendet werden:
out = subprocess.check_output(["cat", "/tmp/baz"])
Sie können auch manuell ein subprocess Objekt konstruieren, wenn Sie feinkörnige Kontrolle müssen:
proc = subprocess.Popen(["cat", "/tmp/baz"], stdout=subprocess.PIPE)
(out, err) = proc.communicate()
Alle diese Funktionen unterstützen Stichwort Parameter anpassen, wie genau die subprocess ausgeführt. Sie können zum Beispiel shell=True
verwenden das Programm durch den Shell ausführen, wenn Sie Dinge wie Dateinamen-Erweiterungen von *
brauchen, aber das kommt mit Einschränkungen .
etw ist richtig . Sie können auch verwenden os.popen (), aber wo verfügbar (Python 2.4 +) subprocess ist in der Regel vorzuziehen.
Im Gegensatz zu einigen Sprachen, die es fördern, ist es im Allgemeinen schlechte Form betrachtet einen Teilprozess, um zu laichen, wo Sie die gleiche Arbeit in der Sprache zu tun. Es ist langsamer, weniger zuverlässig und plattformabhängig. Ihr Beispiel wäre besser dran, wie:
foo= open('/tmp/baz').read()
eta:
baz ist ein Verzeichnis, und ich versuche, den Inhalt aller Dateien in diesem Verzeichnis zu erhalten
? Katze auf einem Verzeichnis wird mir einen Fehler.
Wenn Sie eine Liste von Dateien:
import os
foo= os.listdir('/tmp/baz')
Wenn Sie den Inhalt aller Dateien in einem Verzeichnis wollen, so etwas wie:
contents= []
for leaf in os.listdir('/tmp/baz'):
path= os.path.join('/tmp/baz', leaf)
if os.path.isfile(path):
contents.append(open(path, 'rb').read())
foo= ''.join(contents)
oder, wenn Sie sicher sein können, gibt es keine Verzeichnisse dort, können Sie es in einem Einzeiler passen könnte:
path= '/tmp/baz'
foo= ''.join(open(os.path.join(path, child), 'rb').read() for child in os.listdir(path))
foo = subprocess.check_output(["cat", "/tmp/baz"])
Von Python 3.5 weiter, ist der empfohlene Weg subprocess.run
. Um das gleiche Verhalten wie Sie beschreiben, würden Sie verwenden:
output = subprocess.run("ls", shell=True, stdout=subprocess.PIPE).stdout
Dies wird ein bytes
Objekt zurück. Sie könnten .decode("ascii")
oder .decode("utf-8")
an das Ende anhängen wollen eine str
zu erhalten.
Der einfachste Weg ist, Befehle Paket zu verwenden.
import commands
commands.getoutput("whoami")
Ausgabe:
'bganesan'
import os
foo = os.popen('cat /tmp/baz', 'r').read()
Ich bin mit
(6: 0) $ python --version Python 2.7.1
Eines der Beispiele oben ist:
import subprocess
proc = subprocess.Popen(["cat", "/tmp/baz"], stdout=subprocess.PIPE, shell=True)
(out, err) = proc.communicate()
print "program output:", out
Für mich ist fehlgeschlagen dies das Verzeichnis / tmp zuzugreifen. Nach einem Blick auf dem doc-String für subprocess ersetzt I
[ "prog", "arg"]
mit
"prog arg"
und bekam das Shell-Ausdehnungsverhalten, die gewünscht wurde (a la Perl `prog arg`)
Druck subprocess.Popen ( "ls ld / tmp / v *", stdout = subprocess.PIPE, shell = True) .Kommunizieren () [0]
Ich höre auf Python ein mit Weile zurück, weil ich war verärgert über die Schwierigkeit des Äquivalents von Perl `cmd ...` tun. Ich bin froh, Python zu finden hat diese vernünftig gemacht.
Wenn Sie subprocess.Popen verwenden, denken Sie daran bufsize angeben. Der Standardwert ist 0, was bedeutet, „unbuffered“, nicht „einen angemessenen Standard wählen“.
Dies wird nicht in python3 arbeiten, aber in python2 können Sie str
mit einer benutzerdefinierten __repr__
Methode erweitern, die Shell-Befehl aufruft und gibt es etwa so:
#!/usr/bin/env python
import os
class Command(str):
"""Call system commands"""
def __repr__(cmd):
return os.popen(cmd).read()
Welche Sie können wie Sie mit
#!/usr/bin/env python
from command import Command
who_i_am = `Command('whoami')`
# Or predeclare your shell command strings
whoami = Command('whoami')
who_i_am = `whoami`
Die backtick
( `) Operator wurde entfernt in Python 3
. Es ist zum Verwechseln ähnlich einen Apostroph, und hart, einige Tastaturen tippen auf. Anstelle der backtick
, verwenden, um die äquivalente integrierte Funktion repr()
.