核心概念
在 Python 中操作 PowerShell,主要有两种方式:

- 子流程调用:Python 启动一个子进程,这个进程就是
powershell.exe,Python 和 PowerShell 之间通过命令行参数和标准输入/输出进行通信,这是最常见、最稳定的方式,因为它不依赖于任何 Windows 特定的 COM 接口。 - COM 对象调用:Python 通过 Windows 的 COM (Component Object Model) 接口直接与 PowerShell 引擎交互,这种方式更底层,性能可能更好,但更复杂,且只能在 Windows 上运行。
下面我将重点介绍基于子流程调用的库,因为它们是跨平台(只要目标机器有 PowerShell)、更简单、更健壮的首选。
subprocess - Python 内置库 (基础)
这是最基础的方法,不安装任何第三方库即可使用,它直接执行 PowerShell 命令并捕获输出。
优点:
- 无需安装,Python 标准库自带。
- 功能强大,可以执行任何命令。
缺点:

- 代码稍显冗长。
- 需要手动处理输出、错误和编码问题。
- 管理复杂脚本(如多行脚本、带参数的脚本)比较麻烦。
示例代码
import subprocess
# 1. 执行一个简单的命令
try:
# encoding='utf-8-sig' 可以处理 PowerShell 输出中的 BOM 头
result = subprocess.run(
["powershell", "-Command", "Get-Process | Select-Object -First 5"],
capture_output=True,
text=True,
check=True, # 如果命令返回非零退出码,则抛出 CalledProcessError
encoding='utf-8-sig'
)
print("--- 成功执行 ---")
print(result.stdout)
except subprocess.CalledProcessError as e:
print(f"命令执行失败,返回码: {e.returncode}")
print(f"错误信息: {e.stderr}")
# 2. 传递参数给 PowerShell 命令
# 注意:参数需要用引号括起来,并且要对 Python 的字符串进行转义
hostname_to_check = "localhost"
command = f"Test-Connection -ComputerName '{hostname_to_check}' -Count 1 -Quiet"
try:
result = subprocess.run(
["powershell", "-Command", command],
capture_output=True,
text=True,
check=True,
encoding='utf-8-sig'
)
if result.stdout.strip() == "True":
print(f"{hostname_to_check} 在线。")
else:
print(f"{hostname_to_check} 离线。")
except subprocess.CalledProcessError as e:
print(f"检查主机失败: {e.stderr}")
# 3. 执行多行 PowerShell 脚本
ps_script = """
Get-Service | Where-Object {$_.Status -eq 'Running'} | Select-Object -First 3 | Format-Table Name, DisplayName
"""
try:
# 使用 heredoc ("""...""") 的方式传递脚本
result = subprocess.run(
["powershell", "-Command", ps_script],
capture_output=True,
text=True,
check=True,
encoding='utf-8-sig'
)
print("\n--- 运行中的服务 ---")
print(result.stdout)
except subprocess.CalledProcessError as e:
print(f"脚本执行失败: {e.stderr}")
pypsrp - 功能强大的库
pypsrp 是一个专门用于与 PowerShell Remoting (WinRM) 和本地 PowerShell 会话交互的库,它通过 PowerShell 的 System.Management.Automation.PowerShell .NET 类来执行脚本,比 subprocess 更高效、更“原生”。
优点:
- 性能优于
subprocess,因为不需要启动新的powershell.exe进程(对于本地会话)。 - 可以更好地处理复杂的数据类型,自动将 PowerShell 对象转换为 Python 字典。
- 支持异步操作。
- 是 Ansible Windows 模块的核心依赖之一。
缺点:
- 仅支持 Windows。
- 安装和配置可能比
subprocess稍复杂(尤其是在使用 WinRM 时)。
安装
pip install pypsrp
示例代码 (本地会话)
from pypsrp.powershell import PowerShell, Runspace
from pypsrp.wsman import WSMan
# 本地会话不需要 WSMan,直接使用进程内 Runspace
# 注意:这只能在 Windows 上运行
runspace = Runspace()
try:
# 打开 runspace
runspace.open()
# 创建 PowerShell 对象
ps = PowerShell(runspace)
# 添加一个脚本命令
ps.add_script("Get-Process | Select-Object -First 3")
# 执行脚本
ps.invoke()
# 输出结果
print("--- 使用 pypsrp 执行 ---")
for output in ps.output:
# output 已经被自动转换为字典
print(f"进程名: {output['ProcessName']}, PID: {output['Id']}")
# 清理
ps.dispose()
runspace.close()
except Exception as e:
print(f"发生错误: {e}")
psutil - 跨平台系统信息库 (间接)
虽然 psutil 不是直接调用 PowerShell 的库,但在 Windows 上,它内部会调用 WMI(Windows Management Instrumentation),而 WMI 和 PowerShell 在底层是紧密相关的。psutil 提供了一种更高级、更 Pythonic 的方式来获取系统信息,很多信息你本来可能需要用 Get-Process, Get-Service, Get-Counter 等 PowerShell 命令来获取。

优点:
- 跨平台:同样的代码在 Linux, macOS, Windows 上都能工作。
- 简单易用:API 非常直观,
psutil.process_iter()。 - 无需了解 PowerShell:你只需要知道你想获取什么系统信息即可。
缺点:
- 功能有限:它只覆盖了常见的系统监控功能,无法执行任意 PowerShell 脚本。
示例代码
import psutil
# 获取所有进程,类似于 Get-Process
print("--- 使用 psutil 获取进程 ---")
for proc in psutil.process_iter(['pid', 'name', 'username']):
try:
# proc.info 是一个字典,包含进程信息
print(f"PID: {proc.info['pid']}, Name: {proc.info['name']}, User: {proc.info['username']}")
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
pass
# 获取 CPU 和内存信息,类似于 Get-Counter
print("\n--- CPU 和内存使用率 ---")
print(f"CPU 使用率: {psutil.cpu_percent(interval=1)}%")
print(f"内存使用率: {psutil.virtual_memory().percent}%")
# 获取磁盘信息,类似于 Get-Volume
print("\n--- 磁盘使用情况 ---")
for partition in psutil.disk_partitions():
try:
usage = psutil.disk_usage(partition.mountpoint)
print(f"盘符: {partition.device}, 总空间: {usage.total / (1024**3):.2f} GB, 已用: {usage.used / (1024**3):.2f} GB")
except PermissionError:
# 某些系统盘可能没有访问权限
print(f"盘符: {partition.device} [无访问权限]")
wmi - 直接操作 WMI
WMI (Windows Management Instrumentation) 是 Windows 系统管理的核心,PowerShell 也大量使用它。wmi 库允许你直接通过 Python 访问 WMI 类,这在某些场景下比调用 PowerShell 命令更快、更直接。
优点:
- 直接访问 WMI,性能高。
- 可以获取非常底层的系统信息。
缺点:
- 仅限 Windows。
- WMI 的学习曲线比 PowerShell 更陡峭。
- 库可能不如
psutil或pypsrp活跃。
安装
pip install wmi
示例代码
import wmi
# 创建 WMI 连接
c = wmi.WMI()
# 获取所有正在运行的进程,类似于 Get-Process
print("--- 使用 wmi 获取进程 ---")
for process in c.Win32_Process():
print(f"PID: {process.ProcessId}, Name: {process.Name}")
# 通常我们只取前几个,否则输出会很长
break
# 获取 BIOS 信息
print("\n--- BIOS 信息 ---")
for bios in c.Win32_BIOS():
print(f"制造商: {bios.Manufacturer}, 序列号: {bios.SerialNumber}")
# 获取网络适配器信息
print("\n--- 网络适配器 ---")
for nic in c.Win32_NetworkAdapterConfiguration(IPEnabled=True):
print(f"IP 地址: {nic.IPAddress[0] if nic.IPAddress else 'N/A'}")
总结与选择建议
| 库名 | 类型 | 平台 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|---|
subprocess |
内置 | 跨平台 | 无需安装,功能强大,最稳定 | 代码冗长,处理复杂脚本麻烦 | 快速、简单的任务,执行一次性命令,或作为其他库的备选方案。推荐首选。 |
pypsrp |
第三方 | 仅 Windows | 性能好,支持复杂数据类型,原生 PowerShell 体验 | 仅限 Windows,配置稍复杂 | 需要高性能、频繁交互或在 Ansible 等工具中集成的场景。 |
psutil |
第三方 | 跨平台 | Pythonic API,跨平台,简单易用 | 功能有限,无法执行任意脚本 | 获取通用系统信息(进程、CPU、内存、磁盘等),是系统监控和管理的首选。 |
wmi |
第三方 | 仅 Windows | 直接访问 WMI,性能高,底层信息 | 仅限 Windows,学习曲线陡峭 | 需要获取非常底层或特定的 Windows 系统信息,且性能是关键因素时。 |
最佳实践
- 从
subprocess开始:对于绝大多数任务,使用 Python 内置的subprocess模块就足够了,它简单、可靠且无处不在。 - 处理编码:始终使用
encoding='utf-8-sig',这能很好地处理 PowerShell 输出中可能存在的 UTF-8 BOM 头,避免乱码。 - 错误处理:使用
try...except subprocess.CalledProcessError来捕获 PowerShell 命令执行失败的情况,并检查e.stderr获取详细的错误信息。 - 参数传递:当向 PowerShell 命令传递字符串参数时,务必用单引号 () 括起来,以避免空格等问题。
- 选择高级库:如果你的脚本需要频繁地与 PowerShell 交互,或者性能是瓶颈,再考虑使用
pypsrp,如果你只是需要一些系统信息,psutil通常是更好的选择。
