result = subprocess.run([‘ls’, ‘-l’], capture_output=True, text=True)
process = subprocess.Popen([‘grep’, ‘example’], stdin=subprocess.PIPE, stdout=subprocess.PIPE, text=True)
Затем передайте данные через process.communicate(), чтобы отправить строку в стандартный ввод и получить результат. Этот подход полезен для интерактивных команд или когда требуется передать данные в процессе выполнения.
Не забывайте обрабатывать ошибки. Используйте check=True в subprocess.run(), чтобы вызвать исключение CalledProcessError, если команда завершится с ненулевым кодом возврата. Это помогает избежать неожиданных сбоев и упрощает отладку.
Для повышения производительности в сценариях с множеством команд используйте асинхронные методы, такие как asyncio.create_subprocess_exec. Это позволяет запускать процессы параллельно и эффективно управлять их выполнением. Например:
process = await asyncio.create_subprocess_exec(‘sleep’, ‘5’, stdout=subprocess.PIPE)
import subprocess
result = subprocess.run(['ls'], capture_output=True, text=True)
print(result.stdout)
Для обработки ошибок проверьте атрибут returncode. Если он равен 0, команда выполнена успешно. В противном случае изучите result.stderr:
if result.returncode == 0:
print("Команда выполнена успешно")
else:
print("Ошибка:", result.stderr)
Если нужно выполнить команду с аргументами, передайте их как список. Например, для поиска файлов с расширением .txt:
result = subprocess.run(['find', '.', '-name', '*.txt'], capture_output=True, text=True)
process = subprocess.Popen(['python3', '-u', 'script.py'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, text=True)
stdout, stderr = process.communicate(input='some input')
print(stdout)
В таблице ниже приведены основные параметры функций subprocess.run() и subprocess.Popen():
| Параметр | Описание |
|---|---|
args |
Команда и аргументы в виде списка или строки. |
capture_output |
|
text |
|
stdin |
Позволяет передавать данные в стандартный ввод. |
stdout |
|
stderr |
Указывает, куда перенаправлять стандартные ошибки. |
Для обработки длительных процессов используйте timeout, чтобы избежать зависания программы:
try:
result = subprocess.run(['sleep', '10'], timeout=5)
except subprocess.TimeoutExpired:
print("Процесс завершён по таймауту")
Эти методы помогут вам эффективно работать с командной строкой и получать нужные данные в Python.
import subprocess
result = subprocess.run(["ls", "-l"], capture_output=True, text=True)
print(result.stdout)
Здесь:
["ls", "-l"]– команда и её аргументы в виде списка.
Если нужно обработать ошибки, проверьте атрибут returncode:
if result.returncode != 0:
print("Ошибка:", result.stderr)
Для выполнения более сложных команд, таких как конвейеры, используйте subprocess.Popen:
process = subprocess.Popen(["ls", "-l"], stdout=subprocess.PIPE, text=True)
output, _ = process.communicate()
print(output)
Обработка ошибок при выполнении команд
Используйте параметр check=True в subprocess.run, чтобы автоматически вызывать исключение CalledProcessError, если команда завершится с ненулевым кодом возврата. Это упрощает отслеживание ошибок и предотвращает продолжение выполнения программы при сбое.
try:
result = subprocess.run(['command', 'arg1'], check=True, stderr=subprocess.PIPE)
except subprocess.CalledProcessError as e:
print(f"Ошибка: {e.stderr.decode()}")
Если команда может завершиться с ненулевым кодом, но это не является ошибкой, обработайте результат вручную. Проверьте атрибут returncode и решите, как действовать дальше:
result = subprocess.run(['command', 'arg1'], stderr=subprocess.PIPE)
if result.returncode != 0:
print(f"Предупреждение: {result.stderr.decode()}")
Для работы с длительными процессами используйте timeout, чтобы избежать зависания программы. Если время истекает, будет вызвано исключение TimeoutExpired:
try:
subprocess.run(['command', 'arg1'], timeout=10)
except subprocess.TimeoutExpired:
print("Процесс завершен по таймауту.")
Проверяйте наличие команд и их доступность перед запуском. Используйте shutil.which, чтобы убедиться, что команда существует в системе:
import shutil
if not shutil.which('command'):
raise FileNotFoundError("Команда не найдена.")
Эти подходы помогут эффективно обрабатывать ошибки и обеспечивать стабильную работу вашего скрипта.
Использование аргументов командной строки
Передавайте аргументы командной строки через subprocess.run, используя список строк. Например, для вызова команды ls -l /home, передайте аргументы как ["ls", "-l", "/home"]. Это предотвращает проблемы с пробелами и специальными символами.
Для динамического формирования аргументов используйте переменные. Например, если путь зависит от пользовательского ввода, соберите список аргументов перед вызовом subprocess.run. Это упрощает управление сложными командами.
Если нужно передать аргументы с пробелами или кавычками, оберните их в строки. Например, для команды echo «Hello, World!», используйте ["echo", "Hello, World!"]. Это гарантирует корректную обработку аргументов.
Для работы с аргументами, содержащими переменные среды, используйте параметр env в subprocess.run. Например, передайте словарь с переменными, чтобы переопределить или добавить их в окружение команды.
Проверяйте возвращаемый код завершения через returncode. Если команда завершилась с ошибкой, обработайте её, например, вызвав исключение или логируя результат. Это помогает избежать неожиданных сбоев.
import subprocess
result = subprocess.run(['ls'], stdout=subprocess.PIPE)
print(result.stdout.decode('utf-8'))
Для передачи данных в стандартный ввод процесса используйте stdin=subprocess.PIPE. Это полезно, если команда ожидает ввода от пользователя. Например, для передачи строки в команду grep:
process = subprocess.Popen(['grep', 'hello'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
output, _ = process.communicate(input=b'hello world
')
print(output.decode('utf-8'))
result = subprocess.run(['ls', 'nonexistent_dir'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print(result.stderr.decode('utf-8'))
process = subprocess.Popen(['ping', 'google.com'], stdout=subprocess.PIPE)
for line in iter(process.stdout.readline, b''):
print(line.decode('utf-8').strip())
with open('output.txt', 'w') as f:
subprocess.run(['ls'], stdout=f)
Чтобы избежать блокировки процесса при ожидании завершения команды, используйте timeout в subprocess.run. Это ограничит время выполнения команды:
try:
subprocess.run(['sleep', '10'], timeout=5)
except subprocess.TimeoutExpired:
print('Команда прервана по таймауту')
import subprocess
process = subprocess.Popen(['ping', 'google.com'], stdout=subprocess.PIPE, text=True)
for line in process.stdout:
print(line.strip())
Чтобы избежать блокировки программы, добавьте аргумент bufsize=1, который включает построчное чтение. Это особенно полезно для длительных процессов, таких как ping или tail.
process = subprocess.Popen(['ping', 'google.com'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
import asyncio
async def read_output():
process = await asyncio.create_subprocess_exec('ping', 'google.com', stdout=asyncio.subprocess.PIPE, text=True)
while True:
line = await process.stdout.readline()
if not line:
break
print(line.strip())
asyncio.run(read_output())
Используйте эти методы для мониторинга длительных процессов или анализа логов в реальном времени.
Передача данных в команду через stdin
Для передачи данных в команду через stdin используйте параметр input в функции subprocess.run. Этот параметр принимает строку или байты, которые будут переданы в стандартный ввод процесса. Например, чтобы передать строку «hello» в команду grep, выполните следующий код:
import subprocess
result = subprocess.run(['grep', 'h'], input='hello', text=True, capture_output=True)
print(result.stdout)
Убедитесь, что указали параметр text=True, если передаёте строку. Для байтов этот параметр не нужен. Если данные большие, используйте subprocess.Popen с методом communicate:
process = subprocess.Popen(['grep', 'h'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, text=True)
stdout, stderr = process.communicate(input='hello')
print(stdout)
При работе с бинарными данными передавайте их как байты. Например, для передачи изображения в команду convert из ImageMagick:
with open('image.png', 'rb') as file:
image_data = file.read()
result = subprocess.run(['convert', '-', 'output.jpg'], input=image_data, capture_output=True)
Если команда ожидает ввода построчно, передавайте данные с символами новой строки. Например, для обработки нескольких строк через sed:
input_data = "line1
line2
line3
"
result = subprocess.run(['sed', 's/line/LINE/'], input=input_data, text=True, capture_output=True)
print(result.stdout)
Используйте subprocess.PIPE для более сложных сценариев, где требуется взаимодействие с процессом в реальном времени. Например, для поэтапной передачи данных:
process = subprocess.Popen(['wc', '-l'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, text=True)
process.stdin.write("first line
")
process.stdin.write("second line
")
process.stdin.close()
print(process.stdout.read())
Проверяйте возвращаемые коды завершения и обрабатывайте ошибки с помощью stderr, чтобы убедиться, что команда выполнилась корректно.
Синхронный и асинхронный подходы к выполнению
Для выполнения команд через subprocess в Python используйте синхронный подход, если вам нужно дождаться завершения процесса перед продолжением программы. Это подходит для задач, где последовательность выполнения критична.
- Используйте
subprocess.run()для синхронного выполнения. Например:result = subprocess.run(['ls', '-l'], capture_output=True, text=True) print(result.stdout) - Добавьте параметр
check=True, чтобы программа завершилась с ошибкой, если команда вернет ненулевой код.
Если задача требует параллельного выполнения или работы с несколькими процессами, переходите на асинхронный подход. Это полезно для задач, где время выполнения может варьироваться.
- Используйте
asyncio.create_subprocess_exec()для асинхронного выполнения. Например:async def run_command(): process = await asyncio.create_subprocess_exec('ls', '-l', stdout=asyncio.subprocess.PIPE) stdout, _ = await process.communicate() print(stdout.decode()) asyncio.run(run_command()) - Для управления несколькими процессами одновременно используйте
asyncio.gather().
Синхронный подход проще в реализации, но блокирует выполнение программы. Асинхронный подход требует больше усилий, но позволяет эффективно использовать ресурсы системы. Выбирайте подход в зависимости от задачи.





