物理输入监控 (PIM)
PIM(Physical Input Monitor)提供人机协同保护机制——当检测到用户正在进行物理键盘/鼠标操作时,自动暂停自动化操作,避免冲突。
基本用法
python
from pywxauto import Weixin
# idle_wait=3: 等待用户停止物理输入 3 秒后再执行操作
wx = Weixin(idle_wait=3)
wx.send_text("张三", "hello") # 自动等待物理空闲工作原理
- 通过 Windows 低级钩子(
SetWindowsHookExW)监控物理键盘和鼠标事件 - 排除程序自身注入的虚拟输入(通过
LLKHF_INJECTED/LLMHF_INJECTED标志判断) - 所有带
@PIM.guard装饰器的方法在执行前,会等待物理输入空闲达到指定秒数
上下文管理器
python
from pywxauto import PIM, Weixin
with PIM(idle_wait=3):
wx = Weixin()
wx.send_text("张三", "hello")手动管理
python
from pywxauto import PIM
pim = PIM(idle_wait=3)
if not pim.start():
print("钩子安装失败,物理输入监控未启用")
# ... 执行操作 ...
pim.stop()start() 会等待钩子安装完成并返回是否成功。钩子装不上(权限不足、被安全软件拦截等)时会输出警告并关闭监控,@PIM.guard 随之停止等待 —— 不会出现"以为有保护其实没有"的情况。print(PIM()) 可以查看钩子状态:
<PIM(idle_wait=3, lock_input=False, status=running, kb=True, mouse=True) at 0x...>锁定物理输入
在操作期间锁定用户的键盘鼠标(需要管理员权限):
python
wx = Weixin(idle_wait=3, lock_input=True)
# 每次操作时会先锁定输入,操作完成后解锁手动等待空闲
python
from pywxauto import PIM
PIM.start()
# 等待物理空闲 5 秒
PIM.wait_for_idle(5.0)
# 获取当前空闲时长
idle = PIM.get_idle_duration()
print(f"已空闲 {idle:.1f} 秒")@PIM.guard 装饰器
所有 pywxauto 的 UI 操作方法都带有 @PIM.guard 装饰器。你也可以在自己的代码中使用:
python
from pywxauto import PIM
@PIM.guard
def my_operation():
# 等待 PIM.idle_wait 秒物理空闲
...等待秒数和是否锁定输入都读全局配置(PIM.idle_wait / PIM.lock_input),装饰器没有逐方法开关。想在某个函数里临时多等一会儿,直接调 PIM.wait_for_idle(秒数):
python
def my_critical_operation():
PIM.wait_for_idle(5)
...监控必须已启动,否则等待会被跳过(会输出一条警告):
python
PIM.start() # 或 Weixin(idle_wait=...) 间接启动
my_operation()生成器函数不能用这个装饰器 —— 装饰器只在创建迭代器时执行,等待时机不对。改在函数体开头调用 PIM.ensure_idle():
python
def iter_items():
PIM.ensure_idle() # 等同于 @PIM.guard
...
yield item注意事项
- PIM 仅在
idle_wait > 0时自动启动;只在装饰器上写秒数不会自动启动监控 - 钩子安装失败会警告并关闭监控,不会静默降级为空保护
- PIM 是全局单例,所有状态存储在类变量上
lock_input需要管理员权限,否则BlockInput调用会静默失败block_input()/unblock_input()带引用计数 + 线程归属,嵌套 guard 不会提前解锁, 多线程下也不会出现解锁失败导致键鼠锁死- 监控线程以 daemon 模式运行,主进程退出时自动结束