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.