Відповідь на це питання залежить від версії Python, яку ви використовуєте. Найпростіший підхід полягає у використанні subprocess.check_output
функції:
>>> subprocess.check_output(['ls', '-l'])
b'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
check_output
запускає єдину програму, яка бере лише аргументи як вхідні дані. 1 Він повертає результат точно так, як надруковано stdout
. Якщо вам потрібно написати вхід stdin
, пропустіть вперед до розділів run
або Popen
. Якщо ви хочете виконати складні команди оболонки, дивіться примітку shell=True
в кінці цієї відповіді.
Ця check_output
функція працює майже на всіх версіях Python, які все ще широко використовуються (2.7+). 2 Але для останніх версій це вже не рекомендований підхід.
Сучасні версії Python (3.5 або новіші): run
Якщо ви використовуєте Python 3.5 або новішої версії і не потребуєте зворотної сумісності , рекомендується нова run
функція . Він забезпечує дуже загальний API високого рівня для subprocess
модуля. Щоб захопити вихід програми, передайте subprocess.PIPE
прапор stdout
аргументу ключового слова. Потім відкрийте stdout
атрибут повернутого CompletedProcess
об'єкта:
>>> import subprocess
>>> result = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE)
>>> result.stdout
b'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
Повернене значення - це bytes
об'єкт, тому, якщо ви хочете мати відповідний рядок, вам знадобиться decode
його. Припускаючи, що викликаний процес повертає рядок, закодовану UTF-8:
>>> result.stdout.decode('utf-8')
'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
Це все можна стиснути до однолінійки:
>>> subprocess.run(['ls', '-l'], stdout=subprocess.PIPE).stdout.decode('utf-8')
'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
Якщо ви хочете передати вхід до процесу stdin
, передайте bytes
об'єкт input
аргументу ключового слова:
>>> cmd = ['awk', 'length($0) > 5']
>>> input = 'foo\nfoofoo\n'.encode('utf-8')
>>> result = subprocess.run(cmd, stdout=subprocess.PIPE, input=input)
>>> result.stdout.decode('utf-8')
'foofoo\n'
Ви можете фіксувати помилки, передаючи stderr=subprocess.PIPE
(захоплення в result.stderr
) або stderr=subprocess.STDOUT
(захоплення result.stdout
разом із звичайним результатом). Якщо безпека не викликає занепокоєнь, ви також можете запускати більш складні команди оболонки, передаючи, shell=True
як описано в примітках нижче.
Це додає лише трохи складності, порівняно зі старим способом роботи. Але я вважаю, що це вигідно: тепер ви можете робити майже все, що потрібно, щоб виконати цю run
функцію поодинці.
Старіші версії Python (2.7-3.4): check_output
Якщо ви використовуєте старішу версію Python або вам потрібна скромна зворотна сумісність, ви, ймовірно, можете використовувати check_output
функцію, як коротко описано вище. Він доступний з Python 2.7.
subprocess.check_output(*popenargs, **kwargs)
Він займає такі ж аргументи, як і Popen
(див. Нижче), і повертає рядок, що містить вихід програми. На початку цієї відповіді є більш детальний приклад використання. У Python 3.5 та новіших версіях check_output
еквівалентно виконанню run
з check=True
та stdout=PIPE
та поверненню лише stdout
атрибута.
Ви можете перейти stderr=subprocess.STDOUT
до того , щоб повідомлення про помилки включені в повернутому виході - але в деяких версіях Python переходу stderr=subprocess.PIPE
до check_output
може привести до тупикам . Якщо безпека не викликає занепокоєнь, ви також можете запускати більш складні команди оболонки, передаючи, shell=True
як описано в примітках нижче.
Якщо вам потрібно stderr
передавати або передавати вхід в процес, завдання check_output
не буде вирішено. Дивіться Popen
приклади нижче в цьому випадку.
Складні програми та застарілі версії Python (2.6 та нижче): Popen
Якщо вам потрібна глибока сумісність назад, або якщо вам потрібна більш досконала функціональність, ніж check_output
надається, вам доведеться працювати безпосередньо з Popen
об’єктами, які інкапсулюють API низького рівня для підпроцесів.
Popen
Конструктор приймає або одну команду без аргументів, або список , який містить команду в якості першого елемента, за яким слід будь-яку кількість аргументів, кожен з яких в якості окремого елемента в списку. shlex.split
може допомогти проаналізувати рядки у відповідно відформатованих списках. Popen
Об'єкти також приймають безліч різних аргументів для управління IO процесів та конфігурації низького рівня.
Надіслати вхід і захопити вихідний сигнал communicate
майже завжди є кращим методом. Як і в:
output = subprocess.Popen(["mycmd", "myarg"],
stdout=subprocess.PIPE).communicate()[0]
Або
>>> import subprocess
>>> p = subprocess.Popen(['ls', '-a'], stdout=subprocess.PIPE,
... stderr=subprocess.PIPE)
>>> out, err = p.communicate()
>>> print out
.
..
foo
Якщо ви встановите stdin=PIPE
, communicate
також дозволяє передавати дані в процес через stdin
:
>>> cmd = ['awk', 'length($0) > 5']
>>> p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
... stderr=subprocess.PIPE,
... stdin=subprocess.PIPE)
>>> out, err = p.communicate('foo\nfoofoo\n')
>>> print out
foofoo
Note відповідь Аарон Холла , який вказує на те, що на деяких системах, вам може знадобитися набір stdout
, stderr
і stdin
все PIPE
(або DEVNULL
) , щоб отримати , communicate
щоб працювати на всіх.
У деяких рідкісних випадках вам може знадобитися складне захоплення виходу в реальному часі. Відповідь Vartec пропонує шлях вперед, але інші способи, ніж communicate
схильні до тупикових ситуацій, якщо їх не використовувати обережно.
Як і у всіх перерахованих вище функціях, коли безпека не викликає занепокоєння, ви можете запускати більш складні команди оболонки, передаючи їх shell=True
.
Примітки
1. Запуск команд оболонки: shell=True
аргумент
Як правило, кожен виклик run
, check_output
або Popen
конструктор виконує одну програму . Це означає, що немає фантазійних стилів у стилі баш. Якщо ви хочете запустити складні команди оболонки, ви можете передати shell=True
, які підтримують усі три функції.
Однак це викликає занепокоєння щодо безпеки . Якщо ви робите щось більше, ніж легкий сценарій, вам може бути краще зателефонувати кожен процес окремо і передати висновок від кожного як вхід до наступного, через
run(cmd, [stdout=etc...], input=other_output)
Або
Popen(cmd, [stdout=etc...]).communicate(other_output)
Спокуса безпосередньо підключити труби сильна; протистояти цьому. В іншому випадку, ви , ймовірно , побачити тупики або повинні зробити Hacky таких речей , як це .
2. Однозначні міркування
check_output
повертає рядок у Python 2, але bytes
об’єкт у Python 3. Варто взяти трохи часу, щоб дізнатися про unicode, якщо ви ще цього не зробили.