核心方法概览
主要有以下几种方法可以在 Python 中调用 PowerShell:

subprocess模块:这是最通用、最基础的方法,它通过创建一个新的子进程来执行 PowerShell 命令,适用于几乎所有情况,是理解其他方法的基础。pypsrp(Python PowerShell Remoting Protocol):这是一个专门的第三方库,用于与 PowerShell 远程处理协议 交互,它比subprocess更强大、更底层,可以直接与 PowerShell 引擎通信,性能更好,尤其适合执行复杂的、需要交互的脚本。winrm(Windows Remote Management):通常与pypsrp结合使用,或者通过pywinrm库实现,它主要用于远程管理 Windows 机器,但也可以在本地执行命令。ctypes或pythonnet:这是更底层的方法,直接调用 Windows API 或 .NET 的 CLR(公共语言运行时)。pythonnet更为常用,它允许你直接在 Python 中使用 .NET 程序集,包括System.Management.Automation,这种方法功能最强大,但也最复杂。
对于大多数用户来说,subprocess 和 pypsrp 是最常用和推荐的选择。
使用 subprocess 模块 (最常用)
subprocess 是 Python 的标准库,无需额外安装,它就像在 Windows 的命令提示符 或 PowerShell 终端中手动输入命令一样。
执行简单的 PowerShell 命令
import subprocess
# 要执行的 PowerShell 命令
# 注意:命令字符串最好用单引号括起来,以避免与 Python 的双引号冲突
command = 'Get-Process | Select-Object -First 5'
try:
# 使用 subprocess.run() 执行命令
# shell=True: 表示命令将通过系统的 shell (这里是 PowerShell) 执行
# text=True: 表示将 stdout 和 stderr 解码为文本 (Python 3.7+ 的推荐用法)
# check=True: 如果命令返回非零退出码(表示错误),则会抛出 CalledProcessError 异常
result = subprocess.run(
['powershell.exe', '-Command', command],
capture_output=True,
text=True,
check=True
)
# 打印命令的标准输出
print("命令执行成功!")
print("输出内容:")
print(result.stdout)
except subprocess.CalledProcessError as e:
# 捕获命令执行失败的情况
print(f"命令执行失败,返回码: {e.returncode}")
print(f"错误信息: {e.stderr}")
except FileNotFoundError:
print("错误: 未找到 powershell.exe,请确保您在 Windows 系统上运行。")
代码解释:
['powershell.exe', '-Command', command]: 这是一个列表,推荐使用列表形式而不是字符串,可以避免 shell 注入的风险。powershell.exe: 启动 PowerShell 的可执行文件。-Command: 告诉 PowerShell 接下来要执行一段命令或脚本。command: 要执行的具体命令。
capture_output=True: 捕获命令的标准输出和标准错误。text=True: 将捕获到的字节流解码为字符串。check=True: 自动检查返回码,如果命令失败则抛出异常。
执行复杂的 PowerShell 脚本(多行)
如果你的脚本很长或者包含复杂的逻辑,最好将其保存在一个 .ps1 文件中,然后让 PowerShell 去执行它。

myscript.ps1 文件内容:
# 这是一个示例 PowerShell 脚本 Write-Host "Hello from PowerShell script!" $currentTime = Get-Date Write-Host "Current time is: $currentTime" $osInfo = Get-ComputerInfo Write-Host "OS Name: $($osInfo.WindowsProductName)"
Python 代码 (run_script.py):
import subprocess
import os
# 获取当前脚本所在目录
script_dir = os.path.dirname(os.path.abspath(__file__))
ps1_file_path = os.path.join(script_dir, 'myscript.ps1')
# 使用 -File 参数直接执行 .ps1 文件
# 这种方式比 -Command 更适合执行脚本文件
try:
result = subprocess.run(
['powershell.exe', '-File', ps1_file_path],
capture_output=True,
text=True,
check=True
)
print("脚本执行成功!")
print("输出内容:")
print(result.stdout)
except subprocess.CalledProcessError as e:
print(f"脚本执行失败,返回码: {e.returncode}")
print(f"错误信息: {e.stderr}")
except FileNotFoundError:
print("错误: 未找到 powershell.exe 或脚本文件。")
使用 pypsrp 库 (功能更强大)
pypsrp 是一个专门为 PowerShell 设计的库,它不创建新的 shell 进程,而是直接与 PowerShell 引擎通信,这意味着它更快、更轻量,并且可以更好地处理复杂的脚本和流式输出。
安装 pypsrp
首先需要安装这个库:

pip install pypsrp
执行 PowerShell 命令
from pypsrp.powershell import PowerShell, RunspacePool
from pypsrp.wsman import WSMan
# 连接到本地的 PowerShell 引擎
# 使用 localhost 和默认端口 5985 (HTTP) 或 5986 (HTTPS)
wsman = WSMan("localhost")
runspace_pool = RunspacePool(wsman)
runspace_pool.open()
# 创建 PowerShell 对象
ps = PowerShell(runspace_pool)
# 添加要执行的命令
ps.add_command("Get-Process")
ps.add_parameter("Name", "powershell") # 获取名为 powershell 的进程
try:
# 执行命令并获取结果
# invoke() 会返回一个包含所有输出对象的列表
results = ps.invoke()
print("命令执行成功!")
print("输出内容 (对象形式):")
for item in results:
# 输出是 Process 对象,可以像访问 Python 对象一样访问其属性
print(f" - {item.ProcessName} (PID: {item.Id})")
# 也可以获取原始的输出流
# print("\n原始输出流:")
# print(ps.output)
finally:
# 关闭 runspace,释放资源
runspace_pool.close()
pypsrp 的优势:
- 性能高: 无需创建新进程,直接在现有进程中执行。
- 交互性强: 可以处理流式输出(输出、错误、进度信息),而
subprocess通常需要等待命令结束才能获取所有输出。 - 面向对象: 返回的结果是 PowerShell 对象(如
Process对象),可以直接访问其属性和方法,比解析文本字符串更可靠。
使用 pythonnet 库 (直接调用 .NET)
如果你想直接使用 .NET 的 System.Management.Automation 命名空间,pythonnet 是不二之选。
安装 pythonnet
pip install pythonnet
执行 PowerShell 命令
import clr
# 添加对 PowerShell 程序集的引用
# 这些是 .NET Framework 的标准程序集
clr.AddReference("System.Management.Automation")
clr.AddReference("System.Management.Automation")
# 导入所需的命名空间
from System.Management.Automation import PowerShell, RunspaceConfiguration
# 创建一个空的 runspace 配置
config = RunspaceConfiguration.Create()
# 创建一个 PowerShell 实例
ps = PowerShell.Create(config)
# 添加脚本命令
ps.AddScript("Get-Service | Where-Object {$_.Status -eq 'Running'} | Select-Object -First 3")
try:
# 执行脚本
# invoke() 返回一个 System.Collections.ObjectModel.Collection[IEnumerable]
results = ps.Invoke()
print("命令执行成功!")
print("输出内容 (.NET 对象形式):")
for service in results:
# 输出是 ServiceController 对象
print(f" - {service.ServiceName}: {service.DisplayName}")
except Exception as e:
print(f"执行过程中发生错误: {e}")
# 也可以捕获 PowerShell 的错误流
# for error in ps.Streams.Error.ReadAll():
# print(f"错误: {error.Exception.Message}")
finally:
# 释放资源
ps.Dispose()
总结与选择建议
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
subprocess |
- Python 标准库,无需安装 - 简单易用,适合快速原型 - 可执行任意命令 |
- 性能较差(创建新进程) - 输出是文本,需要手动解析 - 难以处理复杂交互 |
- 简单的一次性命令执行 - 脚本自动化 - 对性能要求不高的场景 |
pypsrp |
- 性能高,不创建新进程 - 输出是对象,易于处理 - 支持流式输出和复杂交互 - 功能强大 |
- 需要安装第三方库 - 概念比 subprocess 稍复杂 |
- 需要高性能的 PowerShell 自动化 - 处理复杂脚本和长任务 - 需要精确解析输出对象 |
pythonnet |
- 功能最强大,直接访问 .NET - 与 .NET 生态系统无缝集成 - 可以调用任何 .NET 库 |
- 安装和配置可能复杂 - 学习曲线陡峭 - 依赖 .NET Framework |
- 需要深度集成 .NET 功能 - 构建复杂的混合 Python/.NET 应用 - 对底层控制有极高要求 |
给你的建议:
- 如果你只是想在 Python 里跑几个简单的 PowerShell 命令,直接使用
subprocess就足够了,它最简单直接。 - 如果你正在构建一个复杂的、需要频繁与 PowerShell 交互的应用,或者发现
subprocess的性能和输出处理方式满足不了你的需求,那么强烈推荐你学习并使用pypsrp,它是为这个任务量身定做的最佳选择。 - 除非你有非常特殊的需求,否则一般不需要使用
pythonnet,因为它引入了额外的复杂性和依赖。
