Эквивалент Bash Backticks в Python
Вопрос
Каков эквивалент обратных ссылок, найденных в Ruby и Perl, в Python?То есть, в Ruby я могу это сделать:
foo = `cat /tmp/baz`
Как выглядит эквивалентный оператор в Python?Я пытался os.system("cat /tmp/baz")
но это приводит результат к стандартному результату и возвращает мне код ошибки этой операции.
Решение
output = os.popen('cat /tmp/baz').read()
Другие советы
Самый гибкий способ - использовать подпроцесс
модуль:
import subprocess
out = subprocess.run(["cat", "/tmp/baz"], capture_output=True)
print("program output:", out)
capture_output
был введен в Python 3.7, для более старых версий вместо него можно использовать специальную функцию check_output ()
:
out = subprocess.check_output(["cat", "/tmp/baz"])
Вы также можете вручную создать объект подпроцесса, если вам нужен детальный контроль:
proc = subprocess.Popen(["cat", "/tmp/baz"], stdout=subprocess.PIPE)
(out, err) = proc.communicate()
Все эти функции поддерживают параметры ключевых слов для настроить, как именно выполняется подпроцесс. Например, вы можете использовать shell = True
для выполнения программы через оболочку, если вам нужны такие вещи, как расширения имен файлов в *
, но они поставляются с ограничения .
sth прав.Вы также можете использовать os.popen(), но там, где доступен подпроцесс (Python 2.4+), как правило, предпочтительнее.
Однако, в отличие от некоторых языков, которые поощряют это, обычно считается дурным тоном создавать подпроцесс, в котором вы можете выполнять ту же работу внутри языка.Это медленнее, менее надежно и зависит от платформы.Ваш пример был бы лучше использовать как:
foo= open('/tmp/baz').read()
eta:
baz - это каталог, и я пытаюсь получить содержимое всех файлов в этом каталоге
?cat в каталоге выдает мне сообщение об ошибке.
Если вам нужен список файлов:
import os
foo= os.listdir('/tmp/baz')
Если вам нужно содержимое всех файлов в каталоге, что-то вроде:
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)
или, если вы можете быть уверены, что там нет каталогов, вы могли бы поместить его в однострочник:
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"])
Начиная с Python 3.5 и далее рекомендуется использовать subprocess.run код>
. Чтобы получить то же поведение, которое вы описываете, вы должны использовать:
output = subprocess.run("ls", shell=True, stdout=subprocess.PIPE).stdout
Это вернет объект bytes
. Возможно, вы захотите добавить .decode (" ascii ")
или .decode (" utf-8 ")
в конец, чтобы получить str .
Самый простой способ - это использовать пакет команд.
import commands
commands.getoutput("whoami")
Выходной сигнал:
"бганесан"
import os
foo = os.popen('cat /tmp/baz', 'r').read()
Я использую
(6: 0) $ python --version Python 2.7.1
Один из приведенных выше примеров:
import subprocess
proc = subprocess.Popen(["cat", "/tmp/baz"], stdout=subprocess.PIPE, shell=True)
(out, err) = proc.communicate()
print "program output:", out
Для меня это не удалось получить доступ к каталогу / tmp. Посмотрев строку документации для подпроцесса, я заменил
[" prog " ;, " arg "]
с
" prog arg " Р>
и получил желаемое поведение расширения оболочки (а-ля Perl `prog arg`)
<Ч>print subprocess.Popen (< ls -ld / tmp / v * " ;, stdout = subprocess.PIPE, shell = True) .communicate () [0]
Некоторое время назад я прекратил использовать python, потому что был раздражен трудностью сделать эквивалент perl `cmd ...`. Я рад, что Python сделал это разумным.
Если вы используете subprocess.Popen, не забудьте указать bufsize. Значение по умолчанию равно 0, что означает «небуферизованный», а не «выбрать разумное значение по умолчанию».
Это не будет работать в python3, но в python2 вы можете расширить str
с помощью специального метода __ repr __
, который вызывает вашу команду оболочки и возвращает ее следующим образом:
#!/usr/bin/env python
import os
class Command(str):
"""Call system commands"""
def __repr__(cmd):
return os.popen(cmd).read()
Который вы можете использовать как
#!/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`
Оператор backtick
(`) был удален в Python 3
. Это похоже на одиночную кавычку и трудно вводить на некоторых клавиатурах. Вместо backtick
используйте эквивалентную встроенную функцию <код> магнезии () код> . р>