Ответ 1
output = os.popen('cat /tmp/baz').read()
Что эквивалентно обратным выводам, найденным в Ruby и Perl в Python? То есть, в Ruby я могу это сделать:
foo = `cat /tmp/baz`
Как выглядит эквивалентный оператор в Python? Я пробовал os.system("cat /tmp/baz")
, но это ставит результат в стандартную версию и возвращает мне код ошибки этой операции.
output = os.popen('cat /tmp/baz').read()
Наиболее гибкий способ - использовать модуль subprocess
:
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()
ет:
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")
Вывод:
'bganesan'
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"
и получил желаемое поведение расширения оболочки (a la 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`
repr()
Оператор backtick
(') был удален в Python 3
. Это похоже на одиночную кавычку и трудно вводить на некоторых клавиатурах. Вместо backtick
используйте эквивалентную встроенную функцию repr()
.