Современные облачные сервисы, например, timeweb.cloud, стали сегодня обыденностью. Удалённый доступ и удалённое управление – основа современного цифрового мира. В нашей сегодняшней статье мы расскажем вам, как запускать внешние процессы при помощи различных модулей в Python 3.
Для запуска внешних программ из Python, а также получения их ввода или вывода используется встроенный модуль subprocess. Данный модуль позволяет запускать и контролировать выполнение различных программ, которые доступны на компьютере.
Чтобы запустить программу с помощью модуля subprocess можно использовать несколько функций: subprocess.run (пришла на замену функции subprocess.call() в версии Python 3.5) и subprocess.Popen.
cloud
subprocess.run(args, *, stdin, input, stdout, stderr,
capture_output, shell, cwd, timeout,
check, encoding, errors, text, env,
universal_newlines)
Аргумент args
– обязательный, через него передается запускаемая программа с аргументами.
Параметры stdin
, input
, stdout
и stderr
отвечают за потоки данных, которые передаются в процесс или выходят из него. Здесь stdout
— поток вывода (результат работы), stderr
— поток ошибок, которые возникли при выполнении. По умолчанию их значения — None.
capture_output
— по умолчанию False, отвечает за захват результата работы процесса (вывода).
Параметр shell
отвечает за способ передачи в процесс программы и ее аргументов — если они представлены как одна строка, следует указать True. По умолчанию False.
cwd
— используется, если требуется указать абсолютный путь к каталогу с запускаемой программой.
timeout
— время в секундах, по истечении которого процесс завершится. При этом возникает исключение.
check
— если имеет значение True, то вызывает исключение, если во время выполнения возникли ошибки. По умолчанию False.
encoding
— отвечает за декодирование вывода.
errors
— если указан, то ошибки кодировки будут вызывать исключение.
text
, universal_newlines
— текстовые режимы для потоков ввода, вывода и ошибок. По умолчанию false.
env
— переменные среды для нового процесса.
Функция возвращает объект CompletedProcess
, содержащий результаты работы. С помощью специальных атрибутов можно получить из этого объекта переданные в функцию аргументы, код результата выполнения, вывод или возникшие ошибки. Работая с этой функцией, необходимо аккуратно работать с кодом из ненадёжных источников, потому что она может выполнять всё подряд, особенно в случае запуска от имени администратора.
Перед тем как рассматривать примеры, импортируем необходимые модули:
from subprocess import run, Popen, PIPE
from sys import executable
python import local file
Значение executable в Python — это абсолютный путь к исполняемому файлу интерпретатора Python. Оно потребуется для запуска кода.
Рассмотрим простой пример применения CompletedProcess
.
run("echo 'Subprocesses are cool!", shell=True)
Вывод:
Subprocesses are cool!
Результатом работы будет объект:
CompletedProcess(args="echo 'Subprocesses are cool!", returncode=0)
Здесь мы видим переданные нами аргументы и статус выполнения (returncode
). Когда статус выполнения равен нулю, это означает, что выполнение завершено успешно.
Рассмотрим сценарий сложнее. В предыдущем примере мы просто запустили внешний процесс и получили ответ, что он успешно выполнен. Но что если мы хотим получить не только статус выполнения, но и какие-то данные вывода? Для этого нам необходимо установить параметр capture_output = True
:
run('ping localhost', shell = True, capture_output = True, encoding='cp866')
В этом примере мы отправляем запрос на localhost для проверки соединения. Параметр encoding
указывает, что нам нужно декодировать результат, иначе мы получим его как байтовую строку.
Чтобы получить вывод программы и ошибки, выполним:
print("stdout:", result.stdout)
print("stderr:", result.stderr)
stdout:
Обмен пакетами с DESKTOP-*** [::1] с 32 байтами данных:
Ответ от ::1: время<1мс
Ответ от ::1: время<1мс
Ответ от ::1: время<1мс
Ответ от ::1: время<1мс
stderr:
В случае, если во время выполнения возникла какая-то ошибка, подпроцесс вернет ее в result.stderr
. В данном случае ошибок не возникло.
Выполним следующий код:
run([executable, "-c", "raise ValueError('It seems there is a mistake!')"], capture_output=True, encoding='cp866')
Элемент -c
– это опция командной строки python, позволяющая передавать на ввод целую программу.
Он сработает без проблем, однако если мы захотим вывести stdout
, то увидим, что он пустой (в отличие от stderr
).
stdout:
stderr: Traceback (most recent call last):
File "<string>", line 1, in <module>
ValueError: It seems there is a mistake!
Если вызвать метод check_returncode
, то мы увидим следующее:
CalledProcessError: Command '['D:\\***\\python.exe', '-c', "raise ValueError('It seems there is a mistake!')"]' returned non-zero exit status 1.
Мы получили ошибку. Для того, чтобы исключение возникало на этапе выполнения подпроцесса, необходимо указать параметр check = True
.
В этом случае код не выполнится, и мы сразу будем знать, что в процессе возникла какая-то проблема.
Мы можем включить ограничение времени выполнения подпроцесса, чтобы программа, которая работает некорректно, не исполнялась бесконечно. Для этого используется параметр timeout
:
run('ping yandex.ru', shell = True, timeout=5, capture_output = True, encoding='cp866')
В случае, если команда выполнилась, мы получим ее вывод:
Обмен пакетами с yandex.ru [77.88.55.50] с 32 байтами данных:
Ответ от 77.88.55.50: число байт=32 время=17мс TTL=56
Ответ от 77.88.55.50: число байт=32 время=17мс TTL=56
Ответ от 77.88.55.50: число байт=32 время=17мс TTL=56
Ответ от 77.88.55.50: число байт=32 время=17мс TTL=56
Если же наша команда не успела закончить выполнение за отведенное время, мы получаем исключение:
TimeoutExpired: Command 'ping yandex.ru' timed out after 1 seconds
С помощью подпроцессов мы также можем запускать установленные программы. Например:
run("notepad.exe")
откроет блокнот.
Также мы можем передавать какой-либо ввод используя stdin
и параметр input
. Выполним код:
run([executable, "-c", "from sys import stdin; print(stdin.read())"], input="Hello subprocess!",capture_output=True, encoding='cp866')
В результате мы получим:
Hello subprocess!
Через Input
можно передавать не только определенный текст, но и вывод программы.
Функция run модуля Subprocess является высокоуровневой. Если для нашей задачи требуется бо́льшая гибкость, то можно использовать напрямую класс Popen. Он имеет схожий синтаксис, однако у него есть несколько дополнительных параметров.
Создадим 2 подпроцесса. В первом мы получим содержимое папки, а с помощью второго выполним сортировку. Чтобы использовать вывод результата первого подпроцесса, мы указываем для него stdout=PIPE
(это значение, которое можно использовать в качестве аргумента для stdin
, stdout
или stderr
).
Чтобы создать связь между двумя процессами, используется метод communicate()
.
p1 = Popen('dir', shell=True, stdin=None, stdout=PIPE, stderr=PIPE)
p2 = Popen('sort /R', shell=True, stdin=p1.stdout)
p1.stdout.close()
out, err = p2.communicate()
Результатом работы этого кода будет вывод отсортированных файлов в папке:
21.03.2022 12:35 <DIR> ..
21.03.2022 12:35 <DIR> .
21.03.2022 12:35 256 test1.py
21.03.2022 12:34 255 test3.py
21.03.2022 12:21 247 test5.py
21.03.2022 12:21 247 test4.py
21.03.2022 12:21 247 test2.py
21.03.2022 12:21 247 test.py
Класс Popen имеет также несколько других полезных методов:
poll()
— проверяет, завершён ли дочерний процесс. Возвращает либо код выполнения, либо None, если процесс еще выполняется.wait(timeout=None)
— ждет завершения дочернего процесса, если указан timeout, то завершается по истечению указанного времени и вызывает исключение TimeoutExpired
.terminate()
— останавливает выполнение процесса.Подготовили для вас выгодные тарифы на облачные серверы
В сегодняшней статье мы рассмотрели, как, используя Python, запустить внешние процессы. Это стандартная возможность библиотеки Python, позволяющая запускать внешние программы и осуществлять вывод.