Запуск консольных команд 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)
Введите имя: Привет, Анна