Якщо ви користуєтеся операційною системою Linux, ви, безсумнівно, оціните можливості команд оболонки.
Коли ви працюєте з Python, ви, можливо, вже розглядали варіанти автоматизації певних процесів. Це, безумовно, ефективний спосіб заощадити час. Ви також можете використовувати сценарії bash для автоматизації задач.
Python є більш зручним для написання сценаріїв, ніж bash, а управління сценаріями Python є більш простим у порівнянні зі сценаріями bash. Підтримка сценаріїв bash може стати складною задачею, особливо коли вони збільшуються в розмірах.
Але що робити, якщо у вас вже є сценарії bash, які ви хочете запускати за допомогою Python?
Чи існує спосіб інтегрувати виконання команд і сценаріїв bash безпосередньо у ваші Python-скрипти?
Так, у Python є вбудований модуль, що називається subprocess
, який спеціально призначений для виконання команд і сценаріїв у Python-програмах. Давайте розглянемо детальніше, як використовувати цей модуль для запуску команд та скриптів bash з ваших Python-програм.
Виконання команд Bash у Python
Як ви вже могли здогадатися, модуль subprocess
є ключовим інструментом для виконання команд і сценаріїв bash. Він пропонує різноманітні методи та класи для цієї мети.
Основними компонентами модуля subprocess
є метод run()
і клас Popen()
. Саме вони забезпечують можливість виконання команд bash у Python-скриптах. Розглянемо кожен з них окремо.
Метод subprocess.run()
Метод subprocess.run()
приймає список рядків як позиційний аргумент. Це обов’язковий параметр, оскільки він містить команду bash та її аргументи. Перший елемент списку – це ім’я команди, а решта – це аргументи до неї.
Розглянемо короткий приклад:
import subprocess subprocess.run(["ls"])
Цей сценарій виведе перелік всіх файлів і директорій у поточному робочому каталозі, де розміщено скрипт. У наведеному вище прикладі команда не має аргументів. Ми надали тільки саму команду bash. Ми можемо додати додаткові аргументи до команди ls
, наприклад, -l
, -a
, -la
і т.д.
Давайте подивимося на приклад із аргументами команди:
import subprocess subprocess.run(["ls", "-la"])
Ця команда відобразить всі файли, включаючи приховані, а також їхні права доступу. Аргумент -la
задає відображення додаткової інформації, включаючи приховані файли та директорії.
Під час написання команд можуть виникати помилки. Якщо ви хочете їх перехопити та обробити пізніше, то це можна зробити за допомогою ключового аргументу stderr
.
Розглянемо приклад:
import subprocess result = subprocess.run(["cat", "sample.txt"], stderr=subprocess.PIPE, text=True) print(result.stderr)
Переконайтеся, що у вашому робочому каталозі немає файлу під назвою sample.txt
. Значення ключового аргументу stderr
встановлено на PIPE
, що дозволяє повернути повідомлення про помилку в об’єкт. Ви потім можете отримати доступ до цього повідомлення за допомогою атрибута stderr
. А text=True
вказує, що результат має бути рядком.
Аналогічно, ви можете отримати вихід команди, використовуючи ключовий аргумент stdout
:
import subprocess result = subprocess.run(["echo", "Hello, World!"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) print(result.stdout)
subprocess.run()
– Вхідні дані
Ви також можете передавати вхідні дані командам за допомогою ключового аргументу input
. Вхідні дані потрібно передавати у вигляді рядка. Тому важливо встановити значення True
для ключового аргументу text
, інакше за замовчуванням вхідні дані будуть прийняті як байти.
Розглянемо приклад:
import subprocess subprocess.run(["python3", "add.py"], text=True, input="2 3")
У цьому прикладі скрипт Python add.py
отримує два числа як вхідні дані. Ми передали ці дані за допомогою ключового аргументу input
.
Клас subprocess.Popen()
Клас subprocess.Popen()
є більш розширеним, ніж метод subprocess.run()
. Він дає більше можливостей для керування процесами, такими як отримання статусу виконання, виводу, передачі вхідних даних тощо.
Існує кілька методів класу subprocess.Popen()
, які вам необхідно знати. Розглянемо їх один за одним разом із прикладами коду.
Метод wait()
Метод wait()
використовується для очікування завершення виконання команди. Наступні рядки Python-коду не виконуватимуться до завершення попередньої команди, до якої застосовується метод wait
. Розглянемо приклад:
import subprocess process = subprocess.Popen(["ls", "-la"]) print("Виконано!")
Запустіть цей код і подивіться на результат. Ви побачите, що “Виконано!” буде надруковано перед виконанням команди ls -la
. Метод wait()
дозволяє уникнути цього, дочекавшись завершення виконання команди:
import subprocess process = subprocess.Popen(["ls", "-la"]) process.wait() print("Виконано!")
Тепер ви побачите, що повідомлення “Виконано!” з’явиться тільки після завершення виконання команди.
Метод communicate()
Метод communicate()
використовується для отримання виводу, повідомлень про помилки та передачі вхідних даних до команди. Він повертає кортеж, який містить вивід та помилки. Розглянемо приклад:
import subprocess process = subprocess.Popen(["echo", "Hello, World!"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) result = process.communicate() print(result)
subprocess.Popen()
– Вхідні дані
Не можна передати вхідні дані класу Popen
безпосередньо. Потрібно скористатися ключовим аргументом stdin
для передачі вхідних даних команді. Екземпляр класу Popen
надає об’єкт stdin
, який має метод write
, що використовується для передачі даних. За замовчуванням, write
приймає дані у вигляді байтових об’єктів, тому важливо вказати text=True
при створенні екземпляра Popen
.
Розглянемо приклад:
import subprocess process = subprocess.Popen(["python3", "add.py"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) process.stdin.write("2 3") process.stdin.close() print(process.stdout.read())
Метод poll()
Метод poll()
використовується для перевірки, чи завершилося виконання команди. Він поверне None
, якщо команда ще виконується. Розглянемо приклад:
import subprocess process = subprocess.Popen(['ping', '-c 5', 'geekflare.com'], stdout=subprocess.PIPE, text=True) while True: output = process.stdout.readline() if output: print(output.strip()) result = process.poll() if result is not None: break
У цьому коді ми використовуємо команду ping
із 5 запитами. Цикл while
повторюється, поки виконання команди не буде завершено. Метод poll
перевіряє статус виконання команди. Якщо poll
повертає значення, відмінне від None
, це означає, що виконання завершено і цикл переривається.
Виконання сценаріїв Bash
Ми розглянули два способи виконання команд. Тепер давайте подивимося, як запускати сценарії bash з Python.
У subprocess
є метод call()
, який спеціально призначений для виконання сценаріїв bash. Цей метод повертає код виходу зі сценарію bash. Стандартний код виходу для сценаріїв bash – це 0. Розглянемо приклад.
Створіть сценарій bash з назвою practice.sh
з наступним вмістом:
#!/bin/bash echo "Hello, World!" exit 1
Тепер напишіть сценарій Python, який виконає цей bash-скрипт:
import subprocess exit_code = subprocess.call('./practice.sh') print(exit_code)
Ви отримаєте наступний результат при запуску цього Python-скрипту:
Hello, World! 1
Висновок
Ми розглянули способи виконання команд та сценаріїв bash у Python. Ви можете використовувати ці знання для більш ефективної автоматизації ваших задач.
Бажаємо вам успішного кодування! 👨💻