2025, Dec 22 00:01
Как запустить PowerShell 7 из Python и получить CommandLine
Почему Get-Process | Format-Table CommandLine из Python даёт пустой вывод. Объясняем разницу версий PowerShell, указываем pwsh.exe и приводим рабочий пример.
Когда вы запускаете PowerShell из Python, все кажется простым, пока не всплывает один нюанс: какой именно движок PowerShell используется. Команда, которая в интерактивной консоли отображается без проблем, при программном запуске может вернуть пустой или вводящий в заблуждение результат — особенно если вы полагаетесь на свойства, доступные только в более новых версиях PowerShell. Частая ловушка — попытка получить свойство CommandLine у объектов процессов.
Воспроизводим проблему
Ниже фрагмент Python, который выполняет конвейер PowerShell и возвращает его отформатированную таблицу. Для обычной таблицы он работает как ожидается:
import subprocess
def collect_ps_table(cmd):
try:
outcome = subprocess.run(
["powershell", "-Command", cmd],
capture_output=True,
text=True,
check=True,
)
return outcome.stdout
except subprocess.CalledProcessError as err:
print(f"Error executing PowerShell command: {err}")
return None
ps_cmd = "Get-Process python | Format-Table -AutoSize"
tabular = collect_ps_table(ps_cmd)
if tabular:
print(tabular)
Но стоит переключить конвейер на запрос свойства CommandLine — и вывод внезапно перестает иметь смысл:
ps_cmd = "Get-Process python | Format-Table CommandLine -AutoSize"
В терминале PowerShell вы можете увидеть результаты, а вот из Python вывод выглядит пустым или «некорректным».
Что на самом деле происходит
Дело не в Python. Всё упирается в то, какой PowerShell вы запускаете. Свойство CommandLine у объектов, возвращаемых Get-Process, доступно в PowerShell (Core) 7. В Windows PowerShell Get-Process это свойство не предоставляет, поэтому форматирование несуществующего свойства приводит к визуально пустому выводу. Коротко говоря:
Проблема не связана с Python, она обусловлена особенностями выполняемой команды PowerShell.
Отсюда и ситуация, когда одна и та же команда «работает» на одном компьютере и не работает на другом: вызываются разные версии PowerShell. На «чистой» системе вы можете обнаружить, что CommandLine просто нет, пока не используете более новый движок. Если вы привязаны к Windows PowerShell и вам нужны командные строки, альтернативой будет запрос Win32_Process: Get-CimInstance -ClassName Win32_Process | Format-Table CommandLine.
Решение: явно указывать PowerShell 7
Направьте вызов subprocess на pwsh.exe из PowerShell 7. С этой заменой запрос CommandLine начинает работать как надо:
import subprocess
def collect_ps_table(cmd):
"""Выполняет команду PowerShell и возвращает вывод отформатированной таблицы в виде строки."""
try:
outcome = subprocess.run(
[r"C:\Program Files\PowerShell\7\pwsh.exe", "-Command", cmd],
capture_output=True,
text=True,
check=True,
)
return outcome.stdout
except subprocess.CalledProcessError as err:
print(f"Error executing PowerShell command: {err}")
return None
ps_cmd = "Get-Process python | Format-Table CommandLine -AutoSize"
tabular = collect_ps_table(ps_cmd)
if tabular:
print(tabular)
Так вы согласуете выполнение из Python с тем, что видите при интерактивной работе в PowerShell (Core) 7.
Почему это важно
Автоматизация часто выполняется в средах, где сосуществуют несколько версий PowerShell. Если ваш код опирается на свойства или поведение, появившиеся в PowerShell 7, вызывайте pwsh.exe явно. Иначе программа может незаметно запустить Windows PowerShell и вернуть пустой результат, особенно при форматировании свойств, которых там нет. Если вывода всё ещё нет или он неожиданный, просмотрите stderr — там нередко оказываются полезные сообщения об ошибках PowerShell.
Итоги
Осознанно выбирайте движок PowerShell, который запускаете из Python. Нужен CommandLine из Get-Process — используйте PowerShell (Core) 7. Если ограничены Windows PowerShell, применяйте команды, которые действительно выдают нужные данные, например запрос к Win32_Process. При разборе странного вывода проверьте потоки ошибок, чтобы понять, в самой ли команде дело, а не в механике subprocess в Python.