Запуск инструкций командной строки из Python
Мостиком для взаимодействия Python и командной строки служит модуль subprocess. С его помощью можно выполнить команду и получить результат ее работы прямо из кода. Предпочтительным способом запуска является функция run.
command
По умолчанию первым аргументом run передается список из команды и ее параметров. Этого достаточно для запуска:
import subprocess subprocess.run(['ls', '-la'])
shell
Также можно задать первый аргумент как строку, но тогда нужно указать флаг shell=True:
subprocess.run('ls -la')
subprocess.run('ls -la', shell=True)capture_output
Опционально можно перехватить потоки вывода и ошибок путем установки флага capture_output=True:
res = subprocess.run('ls -la', shell=True, capture_output=True)
print(res.stdout.decode('utf8'))
print(res.returncode)res = subprocess.run('ls w', shell=True, capture_output=True)
print(res.returncode)
print(res.stderr.decode('utf8'))text
В stdout и stderr по умолчанию возвращается байтовые строки, которые надо декодировать. Иначе можно установить флаг text:
res = subprocess.run('ls -la', shell=True, capture_output=True)
print(res.stdout)res = subprocess.run('ls -la', shell=True, text=True, capture_output=True)
print(res.stdout)encoding
По умолчанию декодирование происходит с кодировкой, которую можно получить так:
import locale locale.getpreferredencoding(False)
Иначе можно задать свою кодировку в параметре encoding.
timeout
Аргумент timeout задает максимальное время (в секундах) ожидания выполнения команды, после выбрасывается исключение TimeoutExpired:
subprocess.run('ls -l', shell=True, capture_output=True, timeout=0.1)
subprocess.run('ls -l', shell=True, capture_output=True, timeout=0.001)check
Если установить флаг check, то при ненулевом коде возврата будет генерироваться исключение CalledProcessError:
subprocess.run('ls -l', shell=True, check=True)
subprocess.run('ls w', shell=True, check=True)input
В параметре input можно задать значение, которое будет передано в stdin:
import sys
result = subprocess.run(
[sys.executable, "-c", "import sys; print(sys.stdin.read())"], capture_output=True, text=True, input="hello"
)
result.stdoutPopen
Внутри run обращается к объекту класса Popen, который обладает более гибкими, но и сложными настройками:
res = subprocess.Popen('ls -la', shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE, text=True).communicate()
# stdout
print(res[0])res = subprocess.Popen('ls w', shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE, text=True).communicate()
# stderr
print(res[1])Интерфейс вызова через класс Popen немного отличается. Главное, что посредством вызова метода communicate запускается дочерней процесс, которому в stdin отправляются данные и считывается результат из stdout и stderr. Для взаимодействия с потоками ввода/вывода указывайте в соответствующих параметрах значение PIPE (метод run так и поступает при capture_output=True).