Jaki jest odpowiednik znaków grawerowanych w języku Ruby i Perl w Pythonie? Oznacza to, że w Rubim mogę to zrobić:
foo = `cat /tmp/baz`
Jak wygląda równoważna instrukcja w Pythonie? Próbowałem, os.system("cat /tmp/baz")
ale to ustawia wynik na standard i zwraca mi kod błędu tej operacji.
Odpowiedzi:
output = os.popen('cat /tmp/baz').read()
źródło
`...`
(przechwytywanie wyjścia standardowego, przekazywanie błędu standardowego) - z jednym wyjątkiem: Ruby umożliwia określenie kodu wyjścia procesu przez$?
po fakcie; w Pythonie, z tego, co wiem, będziesz musiał użyć dosubprocess
tego funkcji modułu.Najbardziej elastycznym sposobem jest użycie
subprocess
modułu:import subprocess out = subprocess.run(["cat", "/tmp/baz"], capture_output=True) print("program output:", out)
capture_output
został wprowadzony w Pythonie 3.7, dla starszych wersjicheck_output()
można zamiast tego użyć funkcji specjalnej :out = subprocess.check_output(["cat", "/tmp/baz"])
Jeśli potrzebujesz precyzyjnej kontroli, możesz również utworzyć obiekt podprocesu ręcznie:
proc = subprocess.Popen(["cat", "/tmp/baz"], stdout=subprocess.PIPE) (out, err) = proc.communicate()
Wszystkie te funkcje obsługują parametry słów kluczowych w celu dostosowania dokładnego sposobu wykonywania podprocesu. Możesz na przykład użyć
shell=True
do wykonania programu przez powłokę, jeśli potrzebujesz takich rzeczy, jak rozszerzenia nazw plików*
, ale wiąże się to z ograniczeniami .źródło
subprocess.run()
(nie wiem, czy na to zasługuje), jeśli nie potrzebujesz obsługi wcześniejszych wersji lub jeśli nie potrzebujesz elastyczności zapewnianej przezPopen()
.coś jest w porządku . Możesz także użyć os.popen (), ale jeśli jest dostępny (Python 2.4+) podproces jest generalnie preferowany.
Jednak w przeciwieństwie do niektórych języków, które do tego zachęcają, generowanie podprocesu, w którym można wykonać tę samą pracę w języku, jest ogólnie uważane za złą formę. Jest wolniejszy, mniej niezawodny i zależny od platformy. Twój przykład byłby lepszy, ponieważ:
foo= open('/tmp/baz').read()
eta:
? cat w katalogu wyświetla mi błąd.
Jeśli chcesz listę plików:
import os foo= os.listdir('/tmp/baz')
Jeśli chcesz zawartość wszystkich plików w katalogu, na przykład:
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)
lub, jeśli możesz być pewien, że nie ma tam katalogów, możesz umieścić go w jednym wierszu:
path= '/tmp/baz' foo= ''.join(open(os.path.join(path, child), 'rb').read() for child in os.listdir(path))
źródło
foo = subprocess.check_output(["cat", "/tmp/baz"])
źródło
Począwszy od Pythona 3.5, zalecanym sposobem jest użycie
subprocess.run
. Od Pythona 3.7, aby uzyskać takie samo zachowanie, jak opisujesz, użyłbyś:cpe = subprocess.run("ls", shell=True, capture_output=True)
To zwróci
subprocess.CompletedProcess
obiekt. Wyjście na stdout będzie wcpe.stdout
, wyjście na stderr będzie wcpe.stderr
, które będąbytes
obiektami. Możesz zdekodować dane wyjściowe, aby uzyskaćstr
obiekt, używająccpe.stdout.decode()
lub otrzymując a, przekazująctext=True
dosubprocess.run
:cpe = subprocess.run("ls", shell=True, capture_output=True, text=True)
W tym drugim przypadku
cpe.stdout
icpe.stderr
oba sąstr
obiektami.źródło
text=True
parametru, aby odzyskać str zamiast bajtów.Najłatwiej jest użyć pakietu poleceń.
import commands commands.getoutput("whoami")
Wynik:
źródło
import os foo = os.popen('cat /tmp/baz', 'r').read()
źródło
używam
Jednym z powyższych przykładów jest:
import subprocess proc = subprocess.Popen(["cat", "/tmp/baz"], stdout=subprocess.PIPE, shell=True) (out, err) = proc.communicate() print "program output:", out
W moim przypadku nie udało się uzyskać dostępu do katalogu / tmp. Po przejrzeniu dokumentacji podprocesu podmieniłem
z
i uzyskał pożądane zachowanie rozszerzania powłoki (a la Perl's „prog arg”)
Zrezygnowałem z używania Pythona jakiś czas temu, ponieważ zirytowała mnie trudność zrobienia odpowiednika perl `cmd ...`. Cieszę się, że Python uczynił to rozsądnym.
źródło
Jeśli używasz subprocess.Popen, pamiętaj o określeniu bufsize. Wartością domyślną jest 0, co oznacza „niebuforowany”, a nie „wybierz rozsądną wartość domyślną”.
źródło
To nie zadziała w python3, ale w python2 możesz rozszerzyć
str
za pomocą niestandardowej__repr__
metody, która wywołuje polecenie powłoki i zwraca ją w następujący sposób:#!/usr/bin/env python import os class Command(str): """Call system commands""" def __repr__(cmd): return os.popen(cmd).read()
Którego możesz użyć jak
#!/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`
źródło
repr()
Operator
backtick
(`) został usunięty wPython 3
. Jest łudząco podobny do pojedynczego cytatu i trudny do wpisania na niektórych klawiaturach. Zamiast tegobacktick
użyj równoważnej funkcji wbudowanejrepr()
.źródło