Введение
Автоматизация взаимодействия с командной строкой необходима во множестве задач: от управления удалёнными серверами до автоматизированного тестирования CLI-интерфейсов. Когда команды требуют интерактивного ввода или ожидания вывода, стандартные средства вроде subprocess
становятся неэффективными. В таких случаях на помощь приходит Pexpect.
Pexpect — мощная библиотека Python для автоматизации управления интерактивными приложениями. Она позволяет запускать процессы, отслеживать их вывод, реагировать на приглашения (prompts), и программно отправлять ввод, имитируя поведение пользователя.
В этой статье мы разберём структуру, принципы работы, все ключевые методы библиотеки Pexpect, и приведём практические кейсы автоматизации.
Основная часть
Установка и подключение
pip install pexpect
Импорт:
import pexpect
Как работает Pexpect
Pexpect создаёт дочерний процесс, перехватывает его stdout/stderr и реагирует на определённые шаблоны (например, текст приглашения к вводу). Это позволяет автоматизировать:
-
Вход по SSH
-
Управление FTP
-
Автоматизацию bash-команд
-
Взаимодействие с CLI-приложениями
-
Обход систем с паролями и авторизацией
Основной класс: spawn
Создание процесса
child = pexpect.spawn("ssh user@host")
Важные параметры:
-
encoding="utf-8"
— обязательно для работы со строками -
timeout=30
— время ожидания вывода -
logfile=sys.stdout
— логгирование процесса
Ожидание вывода
child.expect("password:")
child.sendline("my_password")
Чтение и запись
child.sendline("ls -la")
child.expect(pexpect.EOF)
print(child.before)
Методы класса spawn
Метод | Назначение |
---|---|
expect(pattern) |
Ожидает строку, соответствующую шаблону |
sendline(text) |
Отправляет строку + перенос строки |
send(text) |
Отправляет строку без переноса |
before |
Текст до совпадения шаблона |
after |
Текст совпавший с шаблоном |
read() / readline() |
Чтение вывода |
isalive() |
Проверка, активен ли процесс |
close() |
Завершает процесс |
expect_exact() |
Точное совпадение без регулярных выражений |
expect_list() |
Ждёт одно из нескольких шаблонов |
expect([list]) |
Перебор нескольких выражений с индексом совпадения |
Работа с шаблонами и регулярками
Pexpect позволяет использовать мощные регулярные выражения:
child.expect(r"Password.*:")
Также можно передавать список выражений:
index = child.expect(["Login successful", "Permission denied"])
if index == 0:
print("Success")
else:
print("Failure")
Обработка ошибок и таймаутов
try:
child.expect("#", timeout=10)
except pexpect.TIMEOUT:
print("Timeout error")
except pexpect.EOF:
print("Process ended")
Контроль вывода
child.logfile = open("session.log", "wb")
Функция run()
для простых задач
output, exitstatus = pexpect.run("ls -l", withexitstatus=True)
print(output)
Используется для простых однокомандных сценариев без интерактивности.
Подключение по SSH (пример)
import pexpect
child = pexpect.spawn("ssh user@192.168.0.1", encoding='utf-8')
child.expect("password:")
child.sendline("my_password")
child.expect("#")
child.sendline("ls /home")
child.expect("#")
print(child.before)
Работа с sudo
child = pexpect.spawn("sudo apt update", encoding='utf-8')
child.expect("password for")
child.sendline("my_sudo_pass")
child.expect(pexpect.EOF)
print(child.before)
Запись макросов
Pexpect можно использовать для создания автоматизированных макросов, например, для управления bash-скриптами или UI через терминал.
Интеграция с CI/CD
Pexpect может автоматически управлять CLI-интерфейсами в GitLab CI, Jenkins, GitHub Actions.
script:
- python deploy_script.py
Ключевые кейсы применения
-
Автоматизация SSH и SCP
-
Запуск команд с авторизацией
-
Тестирование CLI-приложений
-
Отладка сетевых взаимодействий
-
Программное взаимодействие с командной строкой
Плюсы и минусы
Преимущества:
-
Гибкость и контроль
-
Поддержка regex
-
Поддержка логирования и отладка
-
Простота интеграции в пайплайны
Ограничения:
-
Не кроссплатформенен полностью (нужен POSIX)
-
Не подходит для GUI
-
Чувствительность к форматированию CLI
Полный список функций и методов Pexpect с пояснениями
1. pexpect.spawn(command, args=[], **kwargs)
Создаёт и запускает дочерний процесс.
Параметры:
-
command
: строка команды (например,'ssh user@host'
) -
args
: список дополнительных аргументов -
timeout
: время ожидания ответа (по умолчанию 30) -
encoding
: кодировка (например,'utf-8'
) -
logfile
: поток для логирования вывода -
echo
: выводить ли обратно введённые данные
Пример:
2. .expect(pattern, timeout=-1, searchwindowsize=None, async_=False)
Ожидает появление текста (или шаблона) во вводе. Самый используемый метод.
Параметры:
-
pattern
: строка, список строк или регулярное выражение -
timeout
: максимум времени ожидания -
searchwindowsize
: размер окна поиска (для больших буферов) -
async_
: асинхронный режим (True / False)
Пример:
3. .expect_exact(pattern_list, timeout=-1)
Как expect()
, но ищет точное совпадение без использования регулярных выражений.
Пример:
4. .sendline(s='')
Отправляет строку (и символ новой строки \n
).
Пример:
5. .send(s)
Отправляет строку без символа новой строки.
Пример:
6. .read()
Считывает весь оставшийся вывод процесса до EOF.
Пример:
7. .readline()
Считывает одну строку вывода.
8. .read_nonblocking(size=1, timeout=-1)
Неблокирующее чтение из stdout дочернего процесса.
9. .readlines()
Считывает все строки до конца.
10. .close()
Закрывает процесс (отправляет EOF и убивает, если не завершился).
11. .isalive()
Возвращает True
, если дочерний процесс всё ещё работает.
12. .wait()
Ожидает завершения процесса и возвращает его exitstatus
.
13. .terminate(force=False)
Прерывает процесс. Если force=True
, убивает его принудительно (SIGKILL
).
14. .kill(signal)
Отправляет сигнал процессу.
Пример:
15. .expect_list(patterns, timeout=-1, searchwindowsize=None, async_=False)
Ожидает первое совпадение из списка шаблонов, возвращает индекс найденного шаблона.
16. .expect_exact_list(patterns, timeout=-1)
То же самое, но для точного сопоставления.
17. .expect_loop(callback)
Выполняет цикл ожидания, передавая события в колбэк-функцию.
18. .interact(escape_character=chr(29), input_filter=None, output_filter=None)
Переходит в интерактивный режим (пользователь управляет процессом вручную).
Пример:
19. .before
Содержит вывод до последнего expect
.
20. .after
Содержит совпавший шаблон после expect
.
21. .match
Возвращает объект совпадения (если использовались регулярные выражения).
22. .buffer
Содержит внутренний буфер.
23. .eof()
Возвращает True
, если дочерний процесс достиг EOF.
24. .terminate(force=False)
Аналог close
, но явно отправляет сигнал SIGTERM
или SIGKILL
.
25. .spawn.read_child()
Считывает из канала stdout дочернего процесса. Используется внутри expect
.
26. pexpect.run(command, timeout=-1, withexitstatus=False, events=None, extra_args=None, logfile=None)
Упрощённая функция для запуска процесса и получения вывода.
Пример:
27. pexpect.TIMEOUT
Исключение, выбрасываемое при превышении таймаута.
28. pexpect.EOF
Исключение, выбрасываемое при достижении конца вывода дочернего процесса.
29. pexpect.ExceptionPexpect
Базовый класс всех исключений Pexpect.
30. pexpect.replwrap.REPLWrapper
Отдельный инструмент для работы с интерактивными оболочками (Python REPL, bash и т.д.).
Пример:
Заключение
Pexpect — мощный инструмент для тех, кто работает с терминалами, серверами и командной строкой. Он позволяет автоматизировать диалоги, обрабатывать интерактивные запросы, управлять сессиями и строить интеллектуальные скрипты CLI-взаимодействия. Эта библиотека идеальна для DevOps-инженеров, разработчиков и QA, которым важно контролировать каждый байт вывода в консоли.