Взаимодействие с программами python

Как запускать внешние процессы, используя Python

Современные облачные сервисы, например, cloud.timeweb.com , стали сегодня обыденностью. Удалённый доступ и удалённое управление – основа современного цифрового мира. В нашей сегодняшней статье мы расскажем вам, как запускать внешние процессы при помощи различных модулей в Python 3 .

Для запуска внешних программ из Python, а также получения их ввода или вывода используется встроенный модуль subprocess . Данный модуль позволяет запускать и контролировать выполнение различных программ, которые доступны на компьютере.

Чтобы запустить программу с помощью модуля subprocess можно использовать несколько функций: subprocess.run (пришла на замену функции subprocess.call() в версии Python 3.5) и subprocess.Popen.

Синтаксис subprocess.run

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. Оно потребуется для запуска кода.

Читайте также:  Javascript onclick open window function

Рассмотрим простой пример применения CompletedProcess .

run("echo 'Subprocesses are cool!", shell=True)

Результатом работы будет объект:

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: время
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 "", line 1, in
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

С помощью подпроцессов мы также можем запускать установленные программы. Например:

Читайте также:  Declare variable in csharp

Также мы можем передавать какой-либо ввод используя stdin и параметр input . Выполним код:

run([executable, "-c", "from sys import stdin; print(stdin.read())"], input="Hello subprocess!",capture_output=True, encoding='cp866')

Через Input можно передавать не только определенный текст, но и вывод программы.

Функция subprocess.run

Функция 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 ..
21.03.2022 12:35 .
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, позволяющая запускать внешние программы и осуществлять вывод.

Источник

Управление Windows приложениями с помощью PowerShell через Telegram бота на Python

Работаю инженером в компании, у которой есть несколько удаленных филиалов и в каждом из них работают сервера видеонаблюдения. Охрана круглосуточно ведет мониторинг происходящего, а приложение видеонаблюдения на этих серверах имеет привычку зависать. Звонки от охраны могут поступать в любое время суток, что очень неудобно, когда ты спишь или нет доступа к ПК, чтобы подключиться удаленно и перезапустить программу

Я начал задумываться о решении данной проблемы путем создания Telegram бота на Python, с помощью которого можно комфортно перезапускать ПО или делегировать это функцию не компетентным людям, например охране

При всем многообразии решений с помощью Telegram ботов, информации на эту тему в интернете мало, поэтому решил поделиться ей здесь, возможно кому то пригодиться

Так же по этому примеру, через запуск скриптов, возможно управлять инфраструктурой серверов предприятия и пр. все зависит от вашей фантазии

Настройка на серверах

Для начала нужно выполнить настройки на серверах (управляемых ПК) с помощью PowerShell, запустить оснастку необходимо от имени администратора

Включить и настроить WinRM на удаленном компьютере:

Enable-PSremoting -skipnetworkprofilecheck –force
Set-executionpolicy remotesigned

На клиентском (управляющем) ПК тоже необходимо выполнить настройки

  • Добавить IP адреса компьютеров, к которым мы будем подключаться в TrustedHosts или же просто разрешить все добавив *
Set-item wsman:\localhost\client\trustedhosts *

Теперь с помощью PowerShell ISE создадим скрипт для запуска/перезапуска процесса программы, которую необходимо перезапустить, тут же можно будет проверить его выполнение

$proc = Get-Process | Where-Object $proc.Kill() Start-Process "C:\apps\Путь к программе "

Далее на серверах создадим простую задачу без триггеров и расписания в планировщике заданий, где укажем только действие на запуск нашего скрипта

Перейдем к настройке клиента

В качестве клиентского компьютера использовалась виртуальная машина с Windows 10

Сервера видеонаблюдения не входят в домен, поэтому придется обойти авторизацию, для этого нам необходимо создать одинаковых пользователей с правами администратора и одинаковым паролем на серверах и клиентском ПК и все действия ниже нужно выполнять под этим пользователем

На клиентском ПК создаем скрипты запуска заданий, которые мы создали на серверах

Invoke-Command -ComputerName 'IP адрес' -ScriptBlock

Чтобы в дальнейшем наш бот смог выполнять эти скрипты, назначаем программу PowerShell для их выполнения по умолчанию, изначально назначен блокнот

Создаем Telegram бота

Находим контакт с именем @BotFather, пишем /newbot, далее указываем название бота

Отсюда нам понадобится token нашего бота

Далее при помощи команды /mybots выбираем и редактируем нашего бота, здесь мы можем настроить меню для запуска наших команд

Устанавливаем Python

Забегая вперед, скажу, что библиотека Python, которую мы будем подключать, почему то работала с ошибками в некоторых версиях Python, я установил PyCharm, Python 3.9.13 вместе с IDE, с ним все работало корректно. Ссылка https://www.jetbrains.com/pycharm/

Далее открываем Cmd или PowerShell от имени администратора и устанавливаем библиотеку для управления нашим ботом

Теперь напишем код нашего Telegram бота

import telepot, time, subprocess def remote(msg): content_type, chat_type, chat_id = telepot.glance(msg) if (content_type == 'text'): command = msg['text'] print ('Got command: %s' % command) if '/address1' in command: #Комманда в Telegram p = subprocess.Popen(expert1, shell=True) #Указываем переменную p = subprocess.Popen(expert2, shell=True) bot.sendMessage(chat_id, "DONE") #Вывод сообщения в чат if '/address2' in command: p = subprocess.Popen(expert3, shell=True) p = subprocess.Popen(expert4, shell=True) p = subprocess.Popen(expert5, shell=True) bot.sendMessage(chat_id, "DONE") if '/address3' in command: p = subprocess.Popen(expert6, shell=True) p = subprocess.Popen(expert7, shell=True) bot.sendMessage(chat_id, "DONE") bot = telepot.Bot('Ваш token Telegam бота') #Указываем token Telegam бота expert1 = 'C:\Telegram\expert1.ps1' #Указваем путь к скрипту expert2 = 'C:\Telegram\expert2.ps1' expert3 = 'C:\Telegram\expert3.ps1' expert4 = 'C:\Telegram\expert4.ps1' expert5 = 'C:\Telegram\expert5.ps1' expert6 = 'C:\Telegram\expert6.ps1' expert7 = 'C:\Telegram\expert7.ps1' bot.message_loop(remote) while 1: time.sleep(20)

Источник

Оцените статью