Эквивалент Bash Backticks в Python

Что эквивалентно обратным ссылкам, найденным в Ruby и Perl в Python? То есть в Ruby я могу сделать это:

foo = `cat /tmp/baz`

Как выглядит эквивалентное утверждение в Python? я пробовал os.system("cat /tmp/baz") но это выводит результат в стандартный формат и возвращает мне код ошибки этой операции.

10 ответов

Решение
output = os.popen('cat /tmp/baz').read()

Самый гибкий способ - это использовать subprocess модуль:

import subprocess

proc = subprocess.Popen(["cat", "/tmp/baz"], stdout=subprocess.PIPE)
(out, err) = proc.communicate()
print "program output:", out

Если вы хотите передать вызов через оболочку, например, чтобы получить расширение имени файла с *, вы можете использовать shell=True параметр. Если вы сделаете это, вы должны предоставить команду в виде строки, заключенной в кавычки /..., как если бы вы вводили ее в командной строке:

proc = subprocess.Popen('cat /tmp/ba* "s p a c e.txt"', shell=True, ...)

это правильно. Вы также можете использовать os.popen(), но там, где это возможно (Python 2.4+), подпроцесс обычно предпочтительнее.

Однако, в отличие от некоторых языков, которые поощряют это, обычно считается плохой формой создавать подпроцесс, где вы можете выполнять ту же работу внутри языка. Это медленнее, менее надежно и зависит от платформы. Ваш пример был бы лучше как:

foo= open('/tmp/baz').read()

ETA:

Баз это каталог, и я пытаюсь получить содержимое всех файлов в этом каталоге

? кошка в каталоге получает мне ошибку.

Если вы хотите список файлов:

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")

Выход:

'Bganesan'

import os
foo = os.popen('cat /tmp/baz', 'r').read()

Я использую

(6:0)$ python - версия 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. Посмотрев строку документации для подпроцесса, я заменил

["прога", "арг"]

с

"прог арг"

и получил желаемое поведение расширения оболочки (а-ля Perl `prog arg`)

print subprocess.Popen ("ls -ld / tmp / v *", stdout = subprocess.PIPE, shell = True).communicate () [0]


Некоторое время назад я прекратил использовать python, потому что меня раздражала сложность создания эквивалента perl `cmd ...`. Я рад, что Python сделал это разумным.

Это не будет работать в 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`

Если вы используете subprocess.Popen, не забудьте указать bufsize. По умолчанию 0, что означает "небуферизованный", а не "выбрать разумное значение по умолчанию".

backtick (`) оператор был удален в Python 3, Это похоже на одиночную кавычку и трудно вводить на некоторых клавиатурах. Вместо backtick, используйте эквивалентную встроенную функцию repr(),

Другие вопросы по тегам