Примеры использования Python в среде Windows
Основные приёмы Python в Windows
Как выполнить внешнюю команду Windows и получить её вывод?
Модуль subprocess является наиболее эффективным и рекомендуемым решением. Он полностью заменяет устаревшие os.system и os.popen и предоставляет гибкий контроль над запускаемыми процессами.
import subprocess
# Запуск команды 'dir' с получением вывода
result = subprocess.run(['cmd', '/c', 'dir', 'C:\\Windows'], capture_output=True, text=True, encoding='cp866')
print(result.stdout[:500]) # Первые 500 символов выводаPython windows пример (примеры python для windows)
Том в устройстве C не имеет метки. Серийный номер тома: XXXX-XXXX Содержимое папки C:\Windows ... (укорочено)
Пояснение: capture_output=True перехватывает stdout и stderr. text=True возвращает строки вместо байтов. Кодировка cp866 нужна для корректного отображения кириллицы в выводе консоли Windows.
Проблема: путь к исполняемому файлу может содержать пробелы. Используйте список аргументов, а не строку с пробелами.
# НЕПРАВИЛЬНО: subprocess.run('"C:\\Program Files\\MyApp\\app.exe" arg', shell=True)
# ПРАВИЛЬНО:
subprocess.run(['C:\\Program Files\\MyApp\\app.exe', 'arg'])
Также возможна ошибка FileNotFoundError, если команда не найдена в PATH. Проверяйте полный путь или используйте which (под Linux) или эквивалент для Windows.
Как запустить команду без получения вывода?
Используйте os.system из модуля os. Он только возвращает код завершения и не позволяет перехватить вывод.
import os
return_code = os.system('start notepad.exe')
print(f'Код завершения: {return_code}')
Недостаток: вывод команды попадает напрямую в консоль. Нельзя получить вывод для анализа. Команды с пробелами требуют кавычек.
Как выполнить команду с передачей данных на вход?
Модуль subprocess с параметром stdin позволяет передать данные в запущенный процесс.
import subprocess
p = subprocess.Popen(['findstr', 'error'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, text=True)
out, _ = p.communicate(input='line1\nline with error\nline2')
print(out)
line with error
Ошибка: если не указать text=True или universal_newlines=True, то данные нужно передавать в байтах.
Как получить информацию о системе (имя, версия, архитектура)?
Модуль platform предоставляет кроссплатформенные функции, а os.environ - доступ к переменным окружения.
import platform, os
print('Система:', platform.system())
print('Версия:', platform.version())
print('Архитектура:', platform.machine())
print('Имя компьютера:', os.environ.get('COMPUTERNAME'))
Система: Windows Версия: 10.0.22631 Архитектура: AMD64 Имя компьютера: PC-USER
Примечание: platform.version() может вернуть номер сборки, а не дружественное имя (например, Windows 10). Для получения версии ОС лучше использовать sys.getwindowsversion().
Как работать с реестром Windows?
Модуль winreg (встроенный) позволяет читать и записывать ключи реестра.
import winreg
# Чтение значения из реестра (путь к PowerShell)
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r'SOFTWARE\Microsoft\PowerShell\1')
value, _ = winreg.QueryValueEx(key, 'InstallPath')
print(value)
winreg.CloseKey(key)
C:\Windows\System32\WindowsPowerShell\v1.0\
Ошибка: доступ к некоторым ключам требует прав администратора (запуск от имени администратора). Используйте try-except для PermissionError.
Как создать ярлык (.lnk) для приложения?
Через COM-объект с помощью pywin32 (установка: pip install pywin32).
import os
import win32com.client
shell = win32com.client.Dispatch('WScript.Shell')
shortcut = shell.CreateShortCut(os.path.expanduser('~/Desktop/MyApp.lnk'))
shortcut.Targetpath = r'C:\Windows\System32\notepad.exe'
shortcut.WorkingDirectory = r'C:\'
shortcut.IconLocation = r'C:\Windows\System32\notepad.exe, 0'
shortcut.Save()
print('Ярлык создан на рабочем столе')
Ярлык создан на рабочем столе
Проблема: модуль win32com не входит в стандартную поставку Python. Если не установлен, возникает ImportError.
Как управлять процессами (завершить, получить список)?
Модуль psutil (сторонний, pip install psutil) даёт удобный интерфейс для работы с процессами.
import psutil
# Список процессов с именем notepad.exe
for proc in psutil.process_iter(['pid', 'name']):
if proc.info['name'] == 'notepad.exe':
print(f'PID: {proc.info["pid"]}')
# Завершить процесс
# proc.terminate()
PID: 1234 PID: 5678
Внимание: proc.terminate() отправляет сигнал, который может быть проигнорирован. Для принудительного завершения используйте proc.kill(). Требуются права администратора для чужих процессов.
Как работать с путями в Windows (разделители, длинные пути)?
Модуль pathlib автоматически адаптируется к платформе.
from pathlib import Path
path = Path('C:') / 'Users' / 'Public' / 'Documents'
print(path.exists()) # True, если существует
print(path.drive) # 'C:'
print(path.parent) # C:\Users\Public
# Для длинных путей (более 260 символов) использовать префикс '\\\\?\
long_path = Path('\\\\?\' + str(path))
print(long_path)
True C: C:\Users\Public \\?\C:\Users\Public
Ошибка: префикс \\?\ работает только с абсолютными путями и требует использования raw-строк или двойного экранирования.
Расширенные примеры работы Python в Windows
Использование Powershell через subprocess
Команды Powershell можно вызывать с параметром -Command.
import subprocess, json
cmd = ['powershell', '-Command', 'Get-Process | Select-Object Name,CPU | ConvertTo-Json']
result = subprocess.run(cmd, capture_output=True, text=True, encoding='utf-8')
try:
data = json.loads(result.stdout)
print(f'Количество процессов: {len(data)}')
for proc in data[:3]:
print(f'{proc["Name"]}: {proc["CPU"]}')
except:
print('Ошибка парсинга: ', result.stderr[:200])
Количество процессов: 120 notepad.exe: 0.12 svchost.exe: 0.45 explorer.exe: 0.78
Создание службы Windows на Python
Используется модуль pywin32 и наследование от win32serviceutil.ServiceFramework.
# pip install pywin32
import servicemanager
import win32serviceutil
import win32service
import win32event
class MyService(win32serviceutil.ServiceFramework):
_svc_name_ = 'TestPythonService'
_svc_display_name_ = 'Test Python Service'
def __init__(self, args):
win32serviceutil.ServiceFramework.__init__(self, args)
self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
def SvcStop(self):
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
win32event.SetEvent(self.hWaitStop)
def SvcDoRun(self):
servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
servicemanager.PYS_SERVICE_STARTED,
(self._svc_name_, ''))
# Основной цикл службы
while True:
if win32event.WaitForSingleObject(self.hWaitStop, 5000) == win32event.WAIT_OBJECT_0:
break
with open('C:\\temp\\service_log.txt', 'a') as f:
f.write(f'Service running at {__import__("datetime").datetime.now()}\n')
if __name__ == '__main__':
win32serviceutil.HandleCommandLine(MyService)
Установка и запуск:
# Установка:
python service.py install
# Запуск:
python service.py start
# Остановка:
python service.py stop
# Удаление:
python service.py remove
Проблема: служба должна быть запущена от имени администратора. Ошибки записываются в журнал приложений Windows. Для отладки можно использовать --debug.
Работа с WMI (Windows Management Instrumentation)
Получение информации о системе через WMI с модулем wmi (pip install wmi).
import wmi
c = wmi.WMI()
for os in c.Win32_OperatingSystem():
print('ОС:', os.Caption)
print('Версия:', os.Version)
print('Архитектура:', os.OSArchitecture)
for disk in c.Win32_LogicalDisk():
if disk.DriveType == 3: # локальный диск
print(f'Диск {disk.DeviceID} - {disk.Size} байт, свободно {disk.FreeSpace}')
ОС: Microsoft Windows 10 Pro Версия: 10.0.22631 Архитектура: 64-разрядная Диск C: - 500105249536 байт, свободно 123456789012
Асинхронный запуск нескольких команд
Использование asyncio с asyncio.create_subprocess_exec для параллельного выполнения.
import asyncio
async def run_command(cmd):
proc = await asyncio.create_subprocess_exec(
*cmd,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE
)
stdout, stderr = await proc.communicate()
return stdout.decode('cp866')
async def main():
cmds = [
['powershell', '-Command', 'Get-Process | Measure-Object'],
['cmd', '/c', 'systeminfo | findstr /C:"Total Physical Memory"'],
]
tasks = [run_command(cmd) for cmd in cmds]
results = await asyncio.gather(*tasks)
for r in results:
print(r.strip()[:100])
if __name__ == '__main__':
asyncio.run(main())
Count : 120 Total Physical Memory: 16,383 MB
Доступ к Windows API через ctypes
Низкоуровневая работа с функциями kernel32, user32 и т.д.
import ctypes
from ctypes import wintypes
# Получение версии Windows через GetVersionEx
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
class OSVERSIONINFOEXW(ctypes.Structure):
_fields_ = [
('dwOSVersionInfoSize', wintypes.DWORD),
('dwMajorVersion', wintypes.DWORD),
('dwMinorVersion', wintypes.DWORD),
('dwBuildNumber', wintypes.DWORD),
('dwPlatformId', wintypes.DWORD),
('szCSDVersion', wintypes.WCHAR * 128),
('wServicePackMajor', wintypes.WORD),
('wServicePackMinor', wintypes.WORD),
('wSuiteMask', wintypes.WORD),
('wProductType', wintypes.BYTE),
('wReserved', wintypes.BYTE),
]
ver = OSVERSIONINFOEXW()
ver.dwOSVersionInfoSize = ctypes.sizeof(OSVERSIONINFOEXW)
ret = kernel32.GetVersionExW(ctypes.byref(ver))
if ret:
print(f'Windows {ver.dwMajorVersion}.{ver.dwMinorVersion} (build {ver.dwBuildNumber})')
else:
print('Не удалось получить версию')
Windows 10.0 (build 22631)
Примечание: GetVersionEx может возвращать неполные данные на Windows 8.1+, более надёжно использовать RtlGetVersion или VerifyVersionInfo. Ошибки доступа приводят к исключениям OSError.
Работа с планировщиком задач через COM
Создание задачи по расписанию с помощью TaskScheduler.
import win32com.client
scheduler = win32com.client.Dispatch('Schedule.Service')
scheduler.Connect()
rootFolder = scheduler.GetFolder('\\')
taskDef = scheduler.NewTask(0)
taskDef.RegistrationInfo.Description = 'Задача создана из Python'
# Триггер: запуск при входе пользователя
trigger = taskDef.Triggers.Create(9) # TASK_TRIGGER_LOGON
trigger.UserId = 'S-1-5-21-...' # SID пользователя
# Действие: запуск notepad.exe
action = taskDef.Actions.Create(0) # TASK_ACTION_EXEC
action.Path = 'notepad.exe'
# Регистрация задачи
rootFolder.RegisterTaskDefinition(
'MyPythonTask',
taskDef,
6, # TASK_CREATE_OR_UPDATE
None, # пользователь
None, # пароль
0, # LOGON_TYPE_PASSWORD
)
print('Задача создана')
Задача создана
Проблема: требуется запуск от имени администратора. SID пользователя можно получить через win32security.LookupAccountName. Ошибка может возникнуть, если задача с таким именем уже существует (использовать флаг TASK_CREATE или TASK_UPDATE).
Графический интерфейс (Tkinter) с иконкой Windows
Пример окна с выбором файла через диалог Windows.
import tkinter as tk
from tkinter import filedialog
import subprocess
def open_file():
path = filedialog.askopenfilename(title='Выберите файл')
if path:
subprocess.Popen(['notepad.exe', path])
root = tk.Tk()
root.title('Пример окна Windows')
btn = tk.Button(root, text='Открыть в блокноте', command=open_file)
btn.pack(pady=20)
root.geometry('300x100')
root.mainloop()
(Открывается окно, после нажатия на кнопку появляется диалог выбора файла и запускается notepad)