Запуск исполняемых файлов (exe) средствами Python

Раздел: Python -> Взаимодействие с ОС

Основные способы запуска EXE из Python

Как надежно запустить exe-файл и дождаться его завершения?

Рекомендуемый способ - модуль subprocess, а именно функция run(). Она позволяет выполнить внешнюю программу, дождаться окончания и получить информацию о результате.

import subprocess

result = subprocess.run(['C:\\Program Files\\MyApp\\app.exe', '--arg1', 'value1'],
                       capture_output=True, text=True, encoding='utf-8')
print('Код возврата:', result.returncode)
print('stdout:', result.stdout)
print('stderr:', result.stderr)

Python run exe file (запуск exe-файла из python)

Объяснение шагов:

  1. Передаётся список, где первый элемент - путь к exe, остальные - аргументы.
  2. capture_output=True - захват stdout и stderr.
  3. text=True - вывод в виде строки, а не байтов.
  4. encoding='utf-8' - кодировка для корректного чтения русского текста.
  5. Результат хранится в объекте CompletedProcess.

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

  • FileNotFoundError - если путь указан неверно. Решение: проверить существование файла через os.path.exists() или использовать абсолютный путь.
  • UnicodeDecodeError - при несовпадении кодировки. Решение: явно указать кодировку (например, 'cp866' для русского вывода в консоли Windows).
  • Программа запускается, но не завершается. Решение: установить timeout в run().

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

Функция os.system() из стандартного модуля os запускает команду в оболочке ОС. Просто, но нет контроля над выводом.

import os

exit_code = os.system('notepad.exe')
print('Код завершения:', exit_code)

Python send files (отправка файлов в python)

Проблемы: нельзя захватить stdout/stderr, код возврата ограничен (только 0 или 1 на некоторых системах), уязвимость к инъекции команд при использовании строк с пользовательским вводом.

Как открыть файл или программу, как при двойном клике?

os.startfile() (Windows) имитирует двойной щелчок по файлу. Открывает exe без ожидания завершения.

import os

os.startfile('C:\\Windows\\System32\\calc.exe')

Python system path (системные вызовы и файловая система в python)

Недостатки: нет возможности передать аргументы или дождаться завершения. Работает только в Windows.

Как запустить программу асинхронно, не дожидаясь её завершения?

subprocess.Popen() даёт полный контроль: запуск в фоне, обмен данными через пайпы.

import subprocess

proc = subprocess.Popen(['ping', '8.8.8.8'],
                        stdout=subprocess.PIPE,
                        stderr=subprocess.PIPE)
# Можно делать другую работу
stdout, stderr = proc.communicate(timeout=10)
print('Вывод:', stdout.decode('cp866'))

Python py file system (работа с файловой системой в python (os, shutil))

  • Зависание при большом выводе без communicate() - решение: читать данные потоково или использовать subprocess.PIPE.
  • Необходимость ручного закрытия пайпов.

Как использовать WinAPI для запуска процесса?

Модуль ctypes позволяет вызывать функции Windows API, такие как CreateProcess.

import ctypes

kernel32 = ctypes.windll.kernel32
kernel32.CreateProcessW(None, 'notepad.exe', None, None, False, 0, None, None, None, None)

аргументы программы python (аргументы командной строки программы на python)

Сложная работа с типами, риск падения интерпретатора при ошибках. Требуется глубокое знание WinAPI.

Как запустить exe с правами администратора или используя ShellExecute?

Библиотека pywin32 (win32api, win32com) предоставляет ShellExecute для запуска с указанием операции (например, 'runas').

import win32api

win32api.ShellExecute(0, 'runas', 'setup.exe', None, None, 1)

Требуется установка pywin32 (pip install pywin32). Непереносимость на Linux/macOS.

Расширенные примеры запуска exe из Python

Ниже приведены более сложные сценарии, демонстрирующие гибкость модуля subprocess и других подходов.

Пример 1: Запуск с таймаутом и обработкой ошибок

Пример
import subprocess

try:
    result = subprocess.run(['timeout', '5'], timeout=3, capture_output=True, text=True)
    print('Команда завершена с кодом:', result.returncode)
except subprocess.TimeoutExpired:
    print('Процесс превысил время ожидания')
Процесс превысил время ожидания

Пример 2: Перенаправление вывода в файл

Пример
import subprocess

with open('output.log', 'w') as f:
    subprocess.run(['dir', '/B'], stdout=f, encoding='cp866', shell=True)

Параметр shell=True позволяет использовать команды оболочки (например, dir).

Пример 3: Запуск скрытого окна (Windows)

Пример
import subprocess

si = subprocess.STARTUPINFO()
si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
si.wShowWindow = subprocess.SW_HIDE

proc = subprocess.Popen(['notepad.exe'], startupinfo=si)
proc.wait()

Пример 4: Передача переменных окружения

Пример
import subprocess, os

my_env = os.environ.copy()
my_env['MY_VAR'] = 'значение'

subprocess.run(['python', '-c', 'import os; print(os.environ["MY_VAR"])'], env=my_env)
значение

Пример 5: Запуск от имени другого пользователя (Windows)

Пример
import win32api

# 'runas' открывает диалог UAC или требует пароль
win32api.ShellExecute(0, 'runas', 'cmd.exe', '/k whoami', None, 1)

Пример 6: Асинхронный запуск с потоковым чтением вывода

Пример
import subprocess, threading

def read_output(stream, label):
    for line in stream:
        print(f'[{label}] {line.decode("cp866").strip()}')

proc = subprocess.Popen(['ping', '8.8.8.8', '-t'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

thread_out = threading.Thread(target=read_output, args=(proc.stdout, 'OUT'))
thread_err = threading.Thread(target=read_output, args=(proc.stderr, 'ERR'))
thread_out.start()
thread_err.start()

import time
time.sleep(3)
proc.terminate()

Результат (сокращён):

[OUT] Ответ от 8.8.8.8: число байт=32 время=45мс TTL=117
[OUT] Ответ от 8.8.8.8: число байт=32 время=44мс TTL=117

Пример 7: Запуск PowerShell скрипта внутри Python

Пример
import subprocess

ps_cmd = 'Get-Process | Where-Object {$_.ProcessName -eq "notepad"} | Format-Table Name, Id'
result = subprocess.run(['powershell', '-Command', ps_cmd], capture_output=True, text=True)
print(result.stdout)
Name    Id
----    --
notepad 1234

Пример 8: Использование ctypes для получения PID созданного процесса

Пример
import ctypes

kernel32 = ctypes.windll.kernel32
class PROCESS_INFORMATION(ctypes.Structure):
    _fields_ = [('hProcess', ctypes.c_void_p),
                ('hThread', ctypes.c_void_p),
                ('dwProcessId', ctypes.c_ulong),
                ('dwThreadId', ctypes.c_ulong)]

class STARTUPINFO(ctypes.Structure):
    _fields_ = [('cb', ctypes.c_ulong),
                ('lpReserved', ctypes.c_wchar_p),
                ('lpDesktop', ctypes.c_wchar_p),
                ('lpTitle', ctypes.c_wchar_p),
                ('dwX', ctypes.c_ulong),
                ('dwY', ctypes.c_ulong),
                ('dwXSize', ctypes.c_ulong),
                ('dwYSize', ctypes.c_ulong),
                ('dwXCountChars', ctypes.c_ulong),
                ('dwYCountChars', ctypes.c_ulong),
                ('dwFillAttribute', ctypes.c_ulong),
                ('dwFlags', ctypes.c_ulong),
                ('wShowWindow', ctypes.c_ushort),
                ('cbReserved2', ctypes.c_ushort),
                ('lpReserved2', ctypes.c_byte * 0),
                ('hStdInput', ctypes.c_void_p),
                ('hStdOutput', ctypes.c_void_p),
                ('hStdError', ctypes.c_void_p)]

si = STARTUPINFO()
si.cb = ctypes.sizeof(si)
pi = PROCESS_INFORMATION()

kernel32.CreateProcessW(None, 'calc.exe', None, None, False, 0, None, None, ctypes.byref(si), ctypes.byref(pi))
print('PID процесса:', pi.dwProcessId)
kernel32.CloseHandle(pi.hProcess)
kernel32.CloseHandle(pi.hThread)
PID процесса: 23456

Запуск exe-файла из Python - comments

En
Python run exe file (python)