Відповідь на це питання залежить від версії 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, якщо ви ще цього не зробили.