Sh – управление shell-командами

онлайн тренер по питону
Онлайн-тренажер Python 3 для начинающих

Теория без воды. Задачи с автоматической проверкой. Подсказки на русском языке. Работает в любом современном браузере.

начать бесплатно

Введение

Во многих проектах на 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>()

Вызов команды как функции.

Примеры:

python
sh.ls("-la") # эквивалент `ls -la` sh.git("status") # эквивалент `git status`

2. Command — объект вызова

sh.ls — это объект Command, у него есть методы и свойства.

Вызов команды:

python
out = sh.echo("Hello, World") print(str(out)) # Hello, World

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).

Пример:

python
try: sh.ls("/nonexistent") except sh.ErrorReturnCode as e: print("Ошибка:", e.stderr)

11. sh.which(command_name)

Возвращает путь к бинарному файлу команды.

python
print(sh.which("python3"))

12. sh.Command(command_path)

Создаёт команду вручную (если имя невалидное или не в PATH).

python
custom = sh.Command("/usr/bin/my_tool") custom("--arg1")

13. sh.pushd(path)

Контекстный менеджер: временно меняет рабочую директорию.

python
with sh.pushd("/tmp"): sh.touch("test.txt")

14. sh.env

Контекстный менеджер для временного изменения переменных окружения.

python
with sh.env(MY_VAR="123"): sh.printenv("MY_VAR")

15. in_= — передача входных данных в STDIN

python
sh.cat(_in="hello\nworld")

16. out= и err= — управление выводом

python
sh.ls("-l", _out=open("out.txt", "w"), _err=open("err.txt", "w"))

17. piped commands — пайпинг как в shell

python
(sh.echo("hello") | sh.grep("h")).stdout # hello

18. _bg=True — запуск в фоне

python
proc = sh.sleep(5, _bg=True) print("Ждём завершения...") proc.wait()

19. _timeout=seconds — ограничение времени выполнения

python
sh.sleep(10, _timeout=2) # выбросит TimeoutException

20. _cwd="path" — запуск из другой директории

python
sh.ls(_cwd="/home/user")

21. _ok_code=[0, 1] — список допустимых exit-кодов

python
sh.mycommand(_ok_code=[0, 1, 2])

22. _tty_in=True / _tty_out=True

Использовать TTY (терминальный ввод/вывод) — полезно для sudo или git.


23. _long_opts={"--opt": "value"} — длинные опции словарём

python
sh.command(_long_opts={"--config": "file.cfg"})

24. _err_to_out=True

Объединяет stderr в stdout.


25. _iter=True — итерация построчно по выводу

python
for line in sh.ls("-l", _iter=True): print(line)

26. _decode=True — авто-декодирование в str

Без этого будет байтовый вывод.


27. _out_bufsize=n

Размер буфера вывода.


28. _bg_exc=False

Отключает выброс исключений в фоне.


Пример полного скрипта

python
import sh try: out = sh.ls("-la", "/nonexistent", _ok_code=[1]) except sh.ErrorReturnCode as e: print("Ошибка выполнения:", e.stderr) with sh.pushd("/tmp"): sh.touch("example.txt") print("Git статус:", sh.git("status"))

Заключение

Sh — это высокоуровневая библиотека для вызова системных команд в Python, обеспечивающая лаконичный и читаемый синтаксис. Она идеально подходит для скриптов автоматизации, работы с DevOps-инструментами и интеграции CLI-интерфейсов в Python-приложения. Благодаря гибкости и минимальному синтаксису, Sh делает оболочку по-настоящему питонизированной.