Вызов и обработка скрипта Shell в Python: практики и ошибки

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Для запуска shell-скрипта из Python применяется команда subprocess.run():

Python
Скопировать код
import subprocess

subprocess.run(['./script.sh'])

Не забывайте о правах на выполнение (используйте chmod +x script.sh) и добавьте шебанг (например, #!/bin/bash), для того чтобы скрипт мог выполниться, как если бы вы его запустили из консоли.

Кинга Идем в IT: пошаговый план для смены профессии

Передача параметров скрипту

Как передать аргументы в скрипт

Добавьте аргументы в список аргументов, чтобы передать их:

Python
Скопировать код
subprocess.run(['./script.sh', 'arg1', 'arg2'])  # скрипт script.sh примет их

Если команда представлена строкой, её можно безопасно разделить на аргументы при помощи shlex.split():

Python
Скопировать код
import shlex, subprocess

command = './script.sh arg1 arg2'  # Изначально это строка
subprocess.run(shlex.split(command))  # Преобразуем в список для корректного запуска

Перехват вывода скрипта

Для получения stdout и stderr используйте subprocess.PIPE:

Python
Скопировать код
result = subprocess.run(['./script.sh'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output, errors = result.stdout, result.stderr

Если вам нужен только вывод, то вы можете использовать subprocess.check_output():

Python
Скопировать код
output = subprocess.check_output(['./script.sh'])  # Мы перехватим весь вывод!

Запускаем скрипт элегантно

Обработка ошибок и исключений

Будьте готовы к возможным ошибкам выполнения, таким как subprocess.CalledProcessError, которые свидетельствуют о ненулевом статусе выхода, и используйте try-except для их обработки:

Python
Скопировать код
try:
    subprocess.check_call(['./script.sh'])
except subprocess.CalledProcessError as e:
    print(f'Произошла ошибка: {e}')  # Мы перехватим и обработаем её

Проверяйте статус выхода для контроля успешности выполнения:

Python
Скопировать код
process = subprocess.run(['./script.sh'])
if process.returncode != 0:  # Здесь что-то пошло не так
    # Обработка исключения

Продвинутое использование subprocess

Для сложных взаимодействий и управления вводом-выводом используйте subprocess.Popen():

Python
Скопировать код
with subprocess.Popen(['./script.sh'], stdout=subprocess.PIPE) as proc:
    log.info(proc.stdout.read())  # Отслеживаем, что выведет процесс

Безопасность превыше всего!

Избегаем уязвимостей безопасности

Не используйте shell=True, чтобы не создавать уязвимостей безопасности. Будьте осторожны с входящими данными и предпочитайте проверенные значения.

Обеспечиваем надёжность скрипта

Ваш скрипт должен быть надёжным. Используйте проверенные источники, бережно храните скрипты и тщательно проверяйте сторонние скрипты на безопасность.

Визуализация

Вашими действиями при вызове shell-скрипта из Python можно представить как управление с помощью пульта (🎮) высокотехнологичным смарт-телевизором (💻):

Markdown
Скопировать код
Код на Python (🎮): "Привет, ТВ, запусти этот shell-скрипт!"
Python
Скопировать код
import subprocess
subprocess.run(['/path/to/script.sh'])

После нажатия кнопки:

Markdown
Скопировать код
🎮 -> 💻: Shell-скрипт успешно запущен!

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

Создаём плавные рабочие процессы

Взаимодействие скрипта и Python

Python и скрипт могут обмениваться данными: Python может обрабатывать вывод shell-скриптов, обеспечивая гибкость обработки:

Python
Скопировать код
import subprocess

# Запускаем процесс обработки данных
completed_process = subprocess.run(['./data_processing.sh'], stdout=subprocess.PIPE)

# Python продолжает обработку
processed_data = completed_process.stdout.decode('utf-8')

Автоматизация задач с Python

Используйте силу Python для создания автоматизированных задач, например, с помощью cron или библиотеки планирования, такой как schedule:

Python
Скопировать код
import schedule
import subprocess

def run_script():
    subprocess.run(['./scheduled_backup.sh'])  # Запускаем резервное копирование

# Планируем задание на 19:00 каждый день
schedule.every().day.at("19:00").do(run_script)

while True:
    schedule.run_pending()
    time.sleep(1)  # Делаем небольшую паузу между итерациями

Учёт различных сред выполнения

При переносе скриптов из разработки в производство важно контролировать изменения среды, используя виртуальные среды, docker-контейнеры или эффективные стратегии путей.

Полезные материалы

  1. subprocess — Управление подпроцессами — Документация Python 3.12.2 — изучите управление подпроцессами.
  2. os — Различные интерфейсы операционной системы — Документация Python 3.12.2 — познакомьтесь с системными вызовами.
  3. shlex — Простой лексический анализ — Документация Python 3.12.2 — узнайте, как разделять строки на аргументы для shell-команд.
  4. Как запускать ваши Python-скрипты и код – Real Python — освойте запуск внешних команд.
  5. python – Как подавить или перехватить вывод subprocess.run()? – Stack Overflow — узнайте секреты подавления или перехвата вывода.