2009-09-11 2 views
73

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

foo = `cat /tmp/baz` 

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

+0

http://stackoverflow.com/questions/2924310/whats-a-good-equivalent-to-pythons-subprocess-check-call-that-returns-the-conte – jfs

ответ

78
output = os.popen('cat /tmp/baz').read() 
+0

Не знаете, как бы я использовал это за пределами примера OP. Ни один из ответов здесь, кажется, не затрагивает чистый вопрос. например. как выполнить 'некоторые функции, приводящие к строке'.somemethod" без лямбда-функций. – mckenzm

+2

@mckenzm Вопрос о захвате вывода внешнего процесса. Захват вывода функции Python будет совсем другим вопросом. –

77

Наиболее гибкий способ заключается в использовании 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, ...) 
+2

Да, это единственный разумный путь, вы можете обернуть его в функцию, чтобы вы могли вызвать что-то вроде execute («command») –

+0

Это на самом деле не работает для меня, так как в этом случае baz является каталогом, и я пытаюсь получить содержимое всех файлов в этом каталоге. (выполнение cat/tmp/baz/* работает в тиках, но не с помощью описанного здесь метода) –

+6

re: «*» не работает; вместо этого используйте подпроцесс.Popen (["cat", "/ tmp/baz"], stdout = subprocess.PIPE, shell = True). Поскольку расширение glob (star) обрабатывается оболочкой, модуль subprocessing должен использовать расширение оболочки в этом случае (предоставляемое/bin/sh). –

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

Это эквивалент обратных ссылок Ruby, но если ваша проблема заключается в том, чтобы перечислить содержимое каталога, то это не лучший способ сделать это. – awatts

25

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

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

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

ет:

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

? 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)) 
+0

Хотя это не был ответ на вопрос, это лучший ответ для обучения пользователей. – noamtm

+0

Заголовок вопроса - «что эквивалентно обратным выводам» .Я предположил, что «кошка» была всего лишь примерной командой. Этот ответ не помогает в общем случае. – Jason

1

Если вы используете subprocess.Popen, не забудьте указать BUFSIZE. Значение по умолчанию равно 0, что означает «небуферизованный», а не «выбор разумного значения по умолчанию».

2

Я использую

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

[ "проги", "аргумент"]

с

"проги арг"

и получил требуемое поведение расширения оболочки (a la Perl argg)

печати subprocess.Popen ("Ls -ld/TMP/v *", стандартный вывод = subprocess.PIPE, оболочки = True) .communicate() [0]


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

14
foo = subprocess.check_output(["cat", "/tmp/baz"]) 
+0

Лучший способ сделать это. :) – Gandaro

+3

Это самый простой Теперь «subprocess.check_output» был добавлен в Python 2.7, который был выпущен в июле 2010 года, после того, как другие «popen» ответили g IVEN. –

4

Самый простой способ - использовать пакет команд.

import commands 

commands.getoutput("whoami") 

Выход:

'bganesan'

+3

Очень просто, но модуль теперь устарел. –

1

Это не будет работать в Python3, но в python2 вы можете расширить str с помощью пользовательского __repr__ метод, который вызывает вашу команду оболочки и возвращает это выглядит так:

#!/usr/bin/env python 

import os 

class Command(str): 
    """Call system commands""" 

    def __repr__(cmd): 
     return os.popen(cmd).read() 

Whic ч вы можете использовать как

#!/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` 
+3

Также вы, вероятно, не должны этого делать * – ThorSummoner

4

С Python 3.5 и далее, рекомендуемый способ заключается в использовании subprocess.run. Для того, чтобы получить такое же поведение, как вы описываете, вы будете использовать:

output = subprocess.run("ls", shell=True, stdout=subprocess.PIPE).stdout 

Это возвращает bytes объект. Возможно, вы захотите добавить .decode("ascii") или .decode("utf-8") до конца, чтобы получить str.

Смежные вопросы