ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Pywin32笔记:用统一 Key 打通 Python 桌面自动化与 AI 工具链

Pywin32笔记:用统一 Key 打通 Python 桌面自动化与 AI 工具链 1. 当 Pywin32 脚本开始需要 AI 能力如果你在用 Pywin32 写 Windows 桌面自动化大概率经历过这个阶段一开始只是FindWindow找窗口、SendMessage填文本框、keybd_event敲回车脚本跑得挺顺。但需求很快会变——比如让脚本读一段界面上的报错文本自动判断该点哪个按钮或者把抓到的表格内容丢给模型做归类再回填到另一个窗口。这时候问题就来了Pywin32 负责的是「手和眼」AI 负责的是「脑子」而这两边的凭证体系完全是两套。我见过太多项目里config.toml里躺着三四个不同平台的 Key每个 Key 的额度、限流、模型名都不一样。脚本里写死一个openai_api_key换模型要改代码加一个工具又要再塞一个 Key。更麻烦的是Pywin32 脚本经常是打包成 exe 丢给同事用的Key 硬编码进去既不安全也没法统一轮换。这篇笔记就从这个痛点出发用 TaoToken 作为统一的 Key 和 API 通道把 Pywin32 桌面自动化和 AI 工具链串起来。适合已经会写基础 Pywin32 脚本、想让脚本「聪明一点」的开发者。核心思路很简单——Pywin32 继续管窗口和输入所有 AI 调用走同一个 base_url 和同一个 Key配置集中到settings.json和config.toml两个文件里。TaoToken 在这里扮演的角色是「统一入口」你不需要在脚本里区分今天调的是哪个模型、走的是哪家通道只需要维护一份凭证。官网在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 入口是 https://taotoken.net/api 下面所有配置都围绕这两个地址展开。2. 前置准备Pywin32 环境与统一 Key2.1 安装 Pywin32 并确认版本先确认你的 Python 环境。Pywin32 对 Python 版本比较敏感建议用 3.9 到 3.11 之间的版本太新的 Python 有时轮子还没跟上。python -m pip install pywin32306 python -m pip install requests装完之后跑一句验证能打印出当前前台窗口标题就说明环境没问题import win32gui hwnd win32gui.GetForegroundWindow() print(win32gui.GetWindowText(hwnd))如果这一步报ImportError: DLL load failed多半是 Pywin32 的后处理脚本没跑执行python Scripts/pywin32_postinstall.py -install路径按你的 Python 安装目录调整即可。2.2 拿到统一 Key去 TaoToken 控制台创建一个 API Key。地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 登录后在 API Keys 页面点新建复制出来的字符串形如sk-xxxxxxxx。这个 Key 就是你后面所有 AI 调用的唯一凭证Pywin32 脚本、命令行工具、编辑器插件都用它。注意Key 只显示一次复制后先存到密码管理器里。不要直接写进会提交到 Git 的代码。2.3 为什么用统一通道而不是多套 Key假设你的 Pywin32 脚本要做三件事识别截图里的文字、把识别结果翻译、根据翻译结果决定点哪个菜单。如果分别接三个平台你要维护三份 Key、三套 base_url、三种请求格式。统一通道之后请求格式收敛成一套 OpenAI 兼容的/v1/chat/completions模型名在请求体里换Key 和地址不变。对 Pywin32 这种「脚本里到处是业务逻辑」的场景少一层凭证管理就少一堆 bug。3. 可复制配置settings.json 与 config.toml 骨架3.1 settings.json给脚本读的运行时配置Pywin32 脚本通常用json读配置最省事因为标准库自带。建一个settings.json{ ai: { base_url: https://taotoken.net/api, api_key: sk-你的Key, default_model: gpt-4o-mini, timeout: 30 }, automation: { target_window_title: 新建文本文档.txt - 记事本, input_edit_class: EDIT, poll_interval: 0.5 } }读取代码import json with open(settings.json, r, encodingutf-8) as f: cfg json.load(f) BASE_URL cfg[ai][base_url] API_KEY cfg[ai][api_key] MODEL cfg[ai][default_model]3.2 config.toml给工具链读的配置如果你同时用命令行工具或编辑器插件它们更认config.toml。放在用户目录下比如C:\Users\你的用户名\.taotoken\config.toml[provider] name taotoken base_url https://taotoken.net/api api_key sk-你的Key [models] default gpt-4o-mini coding claude-3-5-sonnet [request] timeout 30 max_retries 2这样 Pywin32 脚本读settings.json外部工具读config.toml两边指向同一个 base_url 和同一个 Key。换 Key 的时候两个文件一起改或者用环境变量覆盖。3.3 用环境变量兜底生产环境里不要把 Key 写进文件。改成从环境变量读配置文件里留空import os API_KEY os.environ.get(TAOTOKEN_API_KEY) or cfg[ai][api_key]然后在系统环境变量里设TAOTOKEN_API_KEY。Pywin32 脚本打包成 exe 后同事只需要在自己机器上配一次环境变量不用改代码。4. 在 Pywin32 脚本里调用 AI 并验证4.1 封装一个最小的调用函数Pywin32 脚本里调 AI本质就是发一个 HTTP POST。用requests封装import requests def ask_ai(prompt, modelNone): url f{BASE_URL}/v1/chat/completions headers { Authorization: fBearer {API_KEY}, Content-Type: application/json } payload { model: model or MODEL, messages: [ {role: system, content: 你是一个桌面自动化助手只输出简洁结果。}, {role: user, content: prompt} ], temperature: 0.2 } resp requests.post(url, headersheaders, jsonpayload, timeout30) resp.raise_for_status() return resp.json()[choices][0][message][content]4.2 连通性验证先跑通再集成不要一上来就塞进复杂的 Pywin32 流程。先单独跑一个验证脚本if __name__ __main__: result ask_ai(用一句话说明什么是窗口句柄) print(AI 返回, result)看到正常返回就说明 Key、base_url、模型名三者都对。如果报 401检查 Key 有没有多余空格报 404检查 base_url 是不是写成了https://taotoken.net/api/v1正确写法是 base_url 到/api路径里再拼/v1/chat/completions。4.3 把 AI 结果接回 Pywin32 操作验证通过后做一个真实的小闭环读取记事本内容让 AI 判断是否包含关键词包含就点确定按钮。import win32gui, win32con, win32api, time def get_edit_text(hwnd_parent): edit win32gui.FindWindowEx(hwnd_parent, 0, EDIT, None) buf_size win32api.SendMessage(edit, win32con.WM_GETTEXTLENGTH, 0, 0) 1 buf win32gui.PyMakeBuffer(buf_size) win32gui.SendMessage(edit, win32con.WM_GETTEXT, buf_size, buf) address, length win32gui.PyGetBufferAddressAndLen(buf) return win32gui.PyGetString(address, length) hwnd win32gui.FindWindow(0, 新建文本文档.txt - 记事本) if hwnd: text get_edit_text(hwnd) verdict ask_ai(f下面这段文字是否包含错误二字只回答是或否\n{text}) print(AI 判断, verdict) if 是 in verdict: # 这里可以接后续的按钮点击逻辑 pass这段代码把 Pywin32 的窗口读取和 AI 的判断能力串起来了。实测下来WM_GETTEXT拿中文时要注意编码如果返回乱码把PyGetString换成按 gbk 解码的方式。4.4 批量场景下的连接复用如果脚本要循环处理很多窗口每次requests.post都新建连接会慢。用Session复用session requests.Session() session.headers.update({ Authorization: fBearer {API_KEY}, Content-Type: application/json }) def ask_ai_fast(prompt): payload {model: MODEL, messages: [{role: user, content: prompt}]} r session.post(f{BASE_URL}/v1/chat/completions, jsonpayload, timeout30) r.raise_for_status() return r.json()[choices][0][message][content]5. 本篇常见错排查5.1 401 Unauthorized最常见的原因是 Key 复制时带了换行或空格。用print(repr(API_KEY))看一眼正常应该是sk-...没有多余字符。另一个原因是环境变量没生效Pywin32 脚本打包成 exe 后读的是打包时的环境需要在目标机器上重新配。5.2 404 Not Found九成是 base_url 拼错。记住规则base_url 写到https://taotoken.net/api请求路径再拼/v1/chat/completions。如果你在 config.toml 里写成了https://taotoken.net/api/v1代码里又拼一次/v1就会变成/api/v1/v1/...。5.3 窗口句柄找不到FindWindow返回 0 通常是因为窗口标题变了。记事本打开不同文件标题不同用EnumWindows遍历再匹配更稳def find_notepad(): result [] def cb(hwnd, _): if win32gui.IsWindowVisible(hwnd): title win32gui.GetWindowText(hwnd) if 记事本 in title: result.append(hwnd) return True win32gui.EnumWindows(cb, None) return result[0] if result else 05.4 中文乱码Pywin32 的SendMessage设置文本时中文要编码成 gbktext.encode(gbk)。读取时如果PyGetString出来是乱码改用win32gui.PyGetString(address, length)后手动encode(latin1).decode(gbk)试试。5.5 请求超时Pywin32 脚本常在后台跑网络抖动会导致超时。给requests加max_retriesfrom requests.adapters import HTTPAdapter from urllib3.util.retry import Retry retry Retry(total2, backoff_factor0.5, status_forcelist[500, 502, 503]) session.mount(https://, HTTPAdapter(max_retriesretry))6. 把统一 Key 用顺手的几个入口配置跑通之后日常最常用的几个动作可以直接走对应入口省得每次翻文档。需要管理或新建 Key 的时候去 API Keys 页面https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。接入细节和参数说明看文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。想先在网页里试一下模型返回格式用模型对话https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。如果你的 Pywin32 脚本已经不只是「调一次 AI」而是长期跑批、需要稳定额度和多模型切换可以看 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。用 Claude Code 做自动化脚本开发的Anthropic 接入入口在https://taotoken.net/claude-code-anthropic?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。最后留一个我踩过的坑Pywin32 脚本里不要用time.sleep等 AI 返回网络慢的时候会卡住整个自动化流程。改成先发请求、拿到结果再操作窗口或者用线程池把 AI 调用和窗口操作分开。这样即使某次请求慢也不会让鼠标键盘事件错位。
返回列表