杰瑞科技汇

python powershell 库

核心概念

在 Python 中操作 PowerShell,主要有两种方式:

python powershell 库-图1
(图片来源网络,侵删)
  1. 子流程调用:Python 启动一个子进程,这个进程就是 powershell.exe,Python 和 PowerShell 之间通过命令行参数和标准输入/输出进行通信,这是最常见、最稳定的方式,因为它不依赖于任何 Windows 特定的 COM 接口。
  2. COM 对象调用:Python 通过 Windows 的 COM (Component Object Model) 接口直接与 PowerShell 引擎交互,这种方式更底层,性能可能更好,但更复杂,且只能在 Windows 上运行。

下面我将重点介绍基于子流程调用的库,因为它们是跨平台(只要目标机器有 PowerShell)、更简单、更健壮的首选。


subprocess - Python 内置库 (基础)

这是最基础的方法,不安装任何第三方库即可使用,它直接执行 PowerShell 命令并捕获输出。

优点

  • 无需安装,Python 标准库自带。
  • 功能强大,可以执行任何命令。

缺点

python powershell 库-图2
(图片来源网络,侵删)
  • 代码稍显冗长。
  • 需要手动处理输出、错误和编码问题。
  • 管理复杂脚本(如多行脚本、带参数的脚本)比较麻烦。

示例代码

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 命令来获取。

python powershell 库-图3
(图片来源网络,侵删)

优点

  • 跨平台:同样的代码在 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 更陡峭。
  • 库可能不如 psutilpypsrp 活跃。

安装

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 系统信息,且性能是关键因素时。

最佳实践

  1. subprocess 开始:对于绝大多数任务,使用 Python 内置的 subprocess 模块就足够了,它简单、可靠且无处不在。
  2. 处理编码:始终使用 encoding='utf-8-sig',这能很好地处理 PowerShell 输出中可能存在的 UTF-8 BOM 头,避免乱码。
  3. 错误处理:使用 try...except subprocess.CalledProcessError 来捕获 PowerShell 命令执行失败的情况,并检查 e.stderr 获取详细的错误信息。
  4. 参数传递:当向 PowerShell 命令传递字符串参数时,务必用单引号 () 括起来,以避免空格等问题。
  5. 选择高级库:如果你的脚本需要频繁地与 PowerShell 交互,或者性能是瓶颈,再考虑使用 pypsrp,如果你只是需要一些系统信息,psutil 通常是更好的选择。
分享:
扫描分享到社交APP
上一篇
下一篇