Запуск консольных команд Windows через Python: полное руководство

Раздел: Системное администрирование -> Выполнение команд и системные вызовы

Выполнение команд cmd из Python: обзор методов и подводные камни

Как выполнить команду cmd, получив полный контроль над выводом и кодом возврата?

Наиболее эффективный и современный способ - использование модуля subprocess с функцией run(). Этот метод доступен начиная с Python 3.5 и заменяет устаревшие os.system и os.popen. Он обеспечивает безопасность за счёт передачи аргументов в виде списка (избегая shell-инъекций) и позволяет гибко управлять потоками ввода-вывода.

import subprocess

# Выполнение команды 'dir' в Windows cmd
result = subprocess.run(['cmd', '/c', 'dir'], capture_output=True, text=True, encoding='cp866')
print(result.stdout)         # вывод команды
print(result.returncode)     # код возврата (0 - успех)

Python execute command line (выполнение команд командной строки из python)

Пояснение: Первый аргумент - список, где cmd - интерпретатор, /c - ключ для выполнения команды и завершения. capture_output=True перехватывает stdout и stderr. text=True возвращает строки, а не байты. encoding='cp866' используется для корректного отображения кириллицы в Windows.

Типичные ошибки:

  • UnicodeDecodeError - если не указать кодировку, Python может попытаться декодировать вывод в UTF-8, который не подходит для кириллицы в cmd. Решение: указать encoding='cp866' или 'cp1251'.
  • FileNotFoundError - если команда не найдена. Проверьте, что утилита доступна в PATH.
  • TimeoutExpired - если команда зависла. Используйте параметр timeout в run().

Как быстро выполнить команду без перехвата вывода (только код возврата)?

Для простых случаев, когда не важен вывод, можно использовать subprocess.call() или os.system(). Однако os.system() считается устаревшим и менее безопасным.

import subprocess

retcode = subprocess.call(['cmd', '/c', 'echo Hello'])
print(f'Код возврата: {retcode}')

Python exec command (выполнение команды через exec в python)

Проблема: os.system() порождает оболочку cmd.exe, что может привести к проблемам с экранированием спецсимволов. Лучше использовать subprocess.call со списком.

Как получить вывод команды в виде строки без указания кодировки вручную?

Функция subprocess.check_output() возвращает байтовую строку stdout. Для преобразования в текст без явной кодировки можно использовать universal_newlines=True (Python 3.7+) или text=True.

output = subprocess.check_output(['cmd', '/c', 'ver'], universal_newlines=True, encoding='cp866')
print(output)

Cmd commands python (команды cmd в python)

Как выполнить команду с передачей данных на stdin?

proc = subprocess.Popen(['cmd', '/c', 'findstr', 'Python'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, text=True, encoding='cp866')
out, _ = proc.communicate(input='Python\nJava\n')
print(out)

Python 3 commands (команды python 3)

Ошибка: Если забыть закрыть stdin, процесс может зависнуть. communicate() делает это автоматически.

Как выполнить команду с правами администратора?

Для повышения привилегий в Windows используется shell32.ShellExecuteW через ctypes или утилита runas.

import ctypes, sys

def run_as_admin(cmd_line):
    ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, cmd_line, None, 1)

# Пример: запуск ipconfig /flushdns
run_as_admin('cmd /c ipconfig /flushdns')

Проблема: Без прав администратора вызов может быть проигнорирован или выдать ошибку. Всегда проверяйте возвращаемое значение ShellExecuteW.

Продвинутые примеры работы с cmd из Python

Параллельный запуск нескольких команд с контролем времени

Пример
import subprocess
import sys

commands = [
    ['cmd', '/c', 'ping', '-n', '2', '127.0.0.1'],
    ['cmd', '/c', 'ipconfig', '/all'],
    ['cmd', '/c', 'systeminfo'],
]

processes = [subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, encoding='cp866') for cmd in commands]

for proc in processes:
    try:
        stdout, stderr = proc.communicate(timeout=10)
        print(f'Команда завершена с кодом {proc.returncode}')
        print(stdout[:200])
    except subprocess.TimeoutExpired:
        proc.kill()
        print('Процесс превысил время ожидания')
Команда завершена с кодом 0
Ответ от 127.0.0.1: число байт=32 время<1мс TTL=128
...
Команда завершена с кодом 0
Настройка протокола IP для Windows
...

Использование shell=False, но с передачей сложных аргументов

Пример
# Безопасное выполнение команды с пробелами в путях
import subprocess

subprocess.run(['cmd', '/c', 'copy', r'C:\Program Files\App\file.txt', r'C:\Backup\file.txt'], shell=False)

Запуск команды с окружением, отличным от текущего

Пример
import subprocess, os

my_env = os.environ.copy()
my_env['MYVAR'] = 'test'

subprocess.run(['cmd', '/c', 'echo %MYVAR%'], env=my_env, shell=True)
test

Асинхронное выполнение с asyncio

Пример
import asyncio
import sys

async def run_cmd(cmd):
    proc = await asyncio.create_subprocess_exec(
        *cmd,
        stdout=asyncio.subprocess.PIPE,
        stderr=asyncio.subprocess.PIPE
    )
    stdout, stderr = await proc.communicate()
    print(f'[{cmd!r} exited with {proc.returncode}]')
    if stdout:
        print(f'[stdout]\n{stdout.decode("cp866")}')
    if stderr:
        print(f'[stderr]\n{stderr.decode("cp866")}')

async def main():
    await asyncio.gather(
        run_cmd(['cmd', '/c', 'dir']),
        run_cmd(['cmd', '/c', 'ver'])
    )

if __name__ == '__main__':
    if sys.platform == 'win32':
        asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
    asyncio.run(main())
[['cmd', '/c', 'dir'] exited with 0]
[stdout]
 Том в устройстве C не имеет метки...

[['cmd', '/c', 'ver'] exited with 0]
[stdout]

Версия Microsoft Windows [10.0.19045.3803]

Взаимодействие с интерактивной командой через Popen

Пример
import subprocess

proc = subprocess.Popen(
    ['cmd', '/c', 'set /p var=Введите имя: & echo Привет, %var%'],
    stdin=subprocess.PIPE,
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE,
    text=True,
    encoding='cp866'
)
stdout, stderr = proc.communicate(input='Анна\n')
print(stdout)
Введите имя: Привет, Анна

Команды cmd в Python - comments

En
Cmd commands python (python)