Введение
Во многих проектах на Python возникает необходимость вызывать shell-команды: управлять файлами, запускать системные процессы, взаимодействовать с установленными CLI-инструментами. Использовать os.system
или subprocess
можно, но они громоздки и требуют ручной обработки аргументов, ошибок и вывода.
Библиотека Sh предоставляет чистый, питонизированный способ вызывать shell-команды как обычные функции Python. Она значительно упрощает интеграцию внешних утилит, делает код читаемым и легко отлаживаемым.
В этой статье мы рассмотрим возможности библиотеки Sh, её архитектуру, методы, параметры, ограничения, лучшие практики и примеры интеграции.
Основная часть
Установка и подключение
pip install sh
Импорт:
import sh
Основные принципы работы
Sh автоматически маппит имя любой shell-команды на Python-функцию. Это позволяет обращаться к ним так:
print(sh.ls("-l"))
Каждый вызов возвращает объект, содержащий stdout (может быть преобразован в строку, список строк, байты и т.д.).
Примеры базового использования
Список файлов
print(sh.ls("-lah"))
Создание файла
sh.touch("file.txt")
Копирование файла
sh.cp("file.txt", "copy.txt")
Удаление файла
sh.rm("copy.txt")
Работа с аргументами и опциями
Sh поддерживает передачу флагов в виде ключевых аргументов:
sh.ls("--color", "auto")
Или используя сокращения:
sh.ls(a=True, l=True, h=True)
Обработка вывода
Результат команды можно читать как строку:
output = sh.ls()
print(str(output))
Либо построчно:
for line in output:
print(line.strip())
Управление ошибками
try:
sh.rm("non_existent.txt")
except sh.ErrorReturnCode_1 as e:
print("Ошибка:", e.stderr.decode())
Можно перехватывать любые ошибки shell-команд.
Интеграция с пайплайнами
Можно использовать пайпинг:
result = sh.grep("python", _in=sh.ls("-l"))
Поддерживается конвейерная передача данных между командами.
Потоковый ввод и вывод
Запись в команду
sh.cat(_in="Привет из Python\n")
Чтение по мере поступления
proc = sh.tail("-f", "log.txt", _iter=True)
for line in proc:
print(line)
Работа с пользовательскими бинарниками
my_tool = sh.Command("/usr/local/bin/mycli")
my_tool("--run", path="/tmp")
Параллельное выполнение
Можно запускать команды в фоне:
p = sh.sleep(10, _bg=True)
print("Выполняется...")
p.wait()
Безопасность и совместимость
-
Работает в Unix-средах (Linux, macOS)
-
Windows поддерживается частично (через WSL или ограниченно с CMD)
-
Безопаснее, чем
os.system
, не подвержен инъекциям аргументов
Сравнение с другими методами
Метод | Уровень API | Безопасность | Читаемость | Поддержка ошибок |
---|---|---|---|---|
os.system |
Низкий | Низкая | Низкая | Нет |
subprocess |
Средний | Средняя | Средняя | Да |
sh |
Высокий | Высокая | Отличная | Да |
Ключевые кейсы использования
-
Написание утилит DevOps
-
Обёртки для bash-скриптов
-
Автоматизация деплоя
-
Управление системными ресурсами
-
Встраивание CLI-инструментов
Основные функции и методы библиотеки sh
Библиотека работает динамически: она не имеет фиксированного набора функций, потому что любая команда ОС автоматически становится доступной через sh.<command_name>()
.
Но у sh
есть ядро полезных классов и методов, управляющих запуском, выводом, ошибками и т.д.
1. sh.<command>()
Вызов команды как функции.
Примеры:
2. Command
— объект вызова
sh.ls
— это объект Command
, у него есть методы и свойства.
Вызов команды:
3. .run(...)
Запускает команду вручную. Позволяет передавать потоковые аргументы.
4. .wait()
Ожидает завершения команды.
5. .stdout
, .stderr
Доступ к потокам вывода/ошибок.
6. .exit_code
Возвращает код выхода команды.
7. .signal
Если команда завершилась сигналом, можно узнать какой.
8. .pid
PID процесса.
9. .wait()
/ .communicate()
Методы управления жизненным циклом запущенного процесса. Работают как в subprocess
.
10. sh.ErrorReturnCode
Исключение, выбрасываемое при неудачном завершении команды (exit_code != 0
).
Пример:
11. sh.which(command_name)
Возвращает путь к бинарному файлу команды.
12. sh.Command(command_path)
Создаёт команду вручную (если имя невалидное или не в PATH).
13. sh.pushd(path)
Контекстный менеджер: временно меняет рабочую директорию.
14. sh.env
Контекстный менеджер для временного изменения переменных окружения.
15. in_=
— передача входных данных в STDIN
16. out=
и err=
— управление выводом
17. piped commands
— пайпинг как в shell
18. _bg=True
— запуск в фоне
19. _timeout=seconds
— ограничение времени выполнения
20. _cwd="path"
— запуск из другой директории
21. _ok_code=[0, 1]
— список допустимых exit-кодов
22. _tty_in=True
/ _tty_out=True
Использовать TTY (терминальный ввод/вывод) — полезно для sudo или git.
23. _long_opts={"--opt": "value"}
— длинные опции словарём
24. _err_to_out=True
Объединяет stderr
в stdout
.
25. _iter=True
— итерация построчно по выводу
26. _decode=True
— авто-декодирование в str
Без этого будет байтовый вывод.
27. _out_bufsize=n
Размер буфера вывода.
28. _bg_exc=False
Отключает выброс исключений в фоне.
Пример полного скрипта
Заключение
Sh — это высокоуровневая библиотека для вызова системных команд в Python, обеспечивающая лаконичный и читаемый синтаксис. Она идеально подходит для скриптов автоматизации, работы с DevOps-инструментами и интеграции CLI-интерфейсов в Python-приложения. Благодаря гибкости и минимальному синтаксису, Sh делает оболочку по-настоящему питонизированной.