
前言win32com是第三方庫pywin32里的一個(gè)子包作用是讓 Python 通過COMComponent Object Model接口去驅(qū)動(dòng) Windows 上的應(yīng)用程序——最典型的就是本機(jī)安裝的 OfficeExcel、Word、Outlook。它不是 Python 自帶的要先pip install pywin32。三個(gè)必須先建立的認(rèn)知它只在 Windows 上能用。win32com依賴 Windows 的 COM 機(jī)制Linux 和 macOS 上裝了也沒用。它通常要求本機(jī)裝了對(duì)應(yīng)的 Office 應(yīng)用。你不是在「直接讀寫文件」而是啟動(dòng)一個(gè) Office 進(jìn)程讓它替你操作。機(jī)器上沒有 Excel就驅(qū)動(dòng)不了 Excel。本文只給對(duì)象模型層面的使用思路和最小骨架。win32com的方法名、參數(shù)、常量大多直接對(duì)應(yīng) Office 的 VBA 對(duì)象模型版本之間也有差異具體調(diào)用請(qǐng)以 pywin32 的官方文檔和你所用 Office 版本的文檔為準(zhǔn)本文不作為接口參考。一、它和 openpyxl / python-docx 有什么不同新手最常問的就是「既然有openpyxl為什么還要win32com」。答案在兩者的工作方式上維度openpyxl/python-docxwin32com原理直接解析/生成文件格式啟動(dòng) Office 進(jìn)程走 COM 接口需要裝 Office 嗎不需要通常需要跨平臺(tái)可以僅 Windows速度較快適合批量較慢進(jìn)程開銷大能干什么獨(dú)占的事無觸發(fā)真實(shí)計(jì)算引擎、跑宏、打印、導(dǎo)出 PDF、操作 Outlook 收發(fā)郵件穩(wěn)定性不受 Office 版本影響受 Office 版本和安裝狀態(tài)影響一句話取舍只是讀寫文件內(nèi)容優(yōu)先用openpyxl/python-docx需要 Office 的真實(shí)能力重算公式、調(diào)用宏、打印、導(dǎo)出 PDF、驅(qū)動(dòng) Outlook才上win32com。二、基本骨架win32com的入口是win32com.client創(chuàng)建 COM 對(duì)象用Dispatch新建一個(gè)應(yīng)用實(shí)例或GetObject附加到已經(jīng)在運(yùn)行的實(shí)例。之后就是按VBA 對(duì)象模型一層層往下走應(yīng)用 → 工作簿 → 工作表 → 單元格。# 僅適用于 Windows且需要 pip install pywin32# 以下為對(duì)象模型示意具體名稱與參數(shù)以 pywin32 / Office 文檔為準(zhǔn)import win32com.clientexcel win32com.client.Dispatch(Excel.Application) # 拿到 Excel 應(yīng)用對(duì)象excel.Visible False # 后臺(tái)運(yùn)行不彈窗wb excel.Workbooks.Open(rC:\data\book.xlsx)ws wb.Worksheets(1) # 第一個(gè)工作表value ws.Cells(1, 1).Value # 讀 A1ws.Cells(2, 1).Value hello # 寫 A2wb.Close(SaveChangesTrue)excel.Quit()讀這段代碼時(shí)要抓住的重點(diǎn)不是具體方法名而是這套結(jié)構(gòu)Dispatch(Excel.Application)里的字符串叫ProgID不同應(yīng)用用不同的 ProgID。Word、Outlook 各有自己的 ProgID。拿到應(yīng)用對(duì)象后屬性和方法名基本和 VBA 里一致只是.變成了 Python 的屬性訪問。集合用下標(biāo)或名稱訪問索引從 1 開始這是 Office 模型的習(xí)慣和 Python 的 0 基不一樣非常容易搞錯(cuò)。三、早期綁定與后期綁定win32com有兩種調(diào)用風(fēng)格這是它文檔里比較繞的一塊后期綁定late binding用win32com.client.Dispatch(...)調(diào)用時(shí)再動(dòng)態(tài)查找方法。好處是不用額外準(zhǔn)備壞處是沒有代碼補(bǔ)全、常量往往要自己查數(shù)字。早期綁定early binding用win32com.client.gencache.EnsureDispatch(...)之類的方式先生成包裝模塊之后有屬性補(bǔ)全、也能直接用符號(hào)常量。代價(jià)是首次使用會(huì)生成緩存文件Office 版本變了可能要清緩存重建。具體用哪套、緩存放哪、怎么清理都以 pywin32 官方文檔為準(zhǔn)。新手建議先用后期綁定把流程跑通需要常量補(bǔ)全時(shí)再考慮早期綁定。四、實(shí)戰(zhàn)里的幾個(gè)關(guān)鍵點(diǎn)1. 一定要退出應(yīng)用。通過Dispatch啟動(dòng)的 Office 進(jìn)程不會(huì)因?yàn)槟隳_本結(jié)束就自動(dòng)消失必須顯式Quit()。否則你會(huì)看到任務(wù)管理器里堆著一排EXCEL.EXE把內(nèi)存吃光。推薦用try/finally保證退出# 僅適用于 Windowsimport win32com.clientexcel win32com.client.Dispatch(Excel.Application)excel.Visible Falsetry:wb excel.Workbooks.Open(rC:\data\book.xlsx)try:# 在這里操作工作表passfinally:wb.Close(SaveChangesFalse)finally:excel.Quit()2. 逐格操作非常慢。每讀寫一個(gè)單元格就是一次跨進(jìn)程調(diào)用循環(huán)幾千次會(huì)慢到無法忍受。能批量賦值的就批量賦值能關(guān)掉屏幕刷新就關(guān)掉。3. 公式和計(jì)算。這是win32com相對(duì)openpyxl的優(yōu)勢(shì)場(chǎng)景之一Excel 有真正的計(jì)算引擎能算出公式結(jié)果。openpyxl默認(rèn)讀到的是公式字符串或上次保存的緩存值而不是重算后的結(jié)果。4. 宏macro的安全邊界。宏是 Office 里能執(zhí)行任意代碼的機(jī)制。通過win32com觸發(fā)宏等價(jià)于在本機(jī)執(zhí)行那段代碼。因此只對(duì)可信來源的文檔啟用宏不要對(duì)來路不明的文件自動(dòng)運(yùn)行宏處理外部文檔時(shí)保持 Office 的宏安全設(shè)置開啟不要為了方便把它整體關(guān)掉如果腳本要給不特定的人用把「允許運(yùn)行宏」做成顯式開關(guān)而不是默認(rèn)打開。5. 錯(cuò)誤處理。COM 調(diào)用失敗會(huì)拋出 COM 異常具體異常類型以 pywin32 文檔為準(zhǔn)常見的觸發(fā)原因有文件被占用、路徑不存在、Office 裝了但組件未注冊(cè)ProgID 找不到、彈出了需要人工確認(rèn)的對(duì)話框。生產(chǎn)腳本里務(wù)必捕獲并給出清晰提示別讓它靜默失敗。6. 驅(qū)動(dòng)器盤符與路徑。Office 的很多接口對(duì)相對(duì)路徑的理解基準(zhǔn)和你的 Python 進(jìn)程不同它可能相對(duì)于 Office 的當(dāng)前目錄。穩(wěn)妥做法是始終傳絕對(duì)路徑。五、Outlook 的典型用途win32com也能驅(qū)動(dòng) Outlook讀取收件箱、創(chuàng)建草稿、發(fā)送郵件。它和上一節(jié)講的smtplib走的是完全不同的路——smtplib是直接和郵件服務(wù)器對(duì)話win32com走的是本機(jī) Outlook 客戶端。兩者的差別在于用smtplib不依賴 Outlook跨平臺(tái)但需要自己處理認(rèn)證和服務(wù)器配置。用win32com驅(qū)動(dòng) Outlook用的是本機(jī)已登錄的賬號(hào)不需要配服務(wù)器但只能在裝好 Outlook 的 Windows 上跑。同樣地發(fā)送郵件要遵守服務(wù)條款不要用于群發(fā)營銷賬號(hào)口令不要硬編碼在腳本里。具體對(duì)象和方法名以 Office 的 Outlook 對(duì)象模型文檔為準(zhǔn)。常見坑點(diǎn)在非 Windows 上裝 pywin32? 在 Linux/macOS 上import win32com直接失敗 ? 這是 Windows 專有庫跨平臺(tái)需求改用openpyxl、python-docx、smtplib忘了Quit()? 腳本跑完就結(jié)束任務(wù)管理器里殘留一堆EXCEL.EXE? 用try/finally保證excel.Quit()一定執(zhí)行以為沒裝 Office 也能用? 服務(wù)器上只裝了 pywin32 就Dispatch(Excel.Application)? 多數(shù)場(chǎng)景要求本機(jī)裝有對(duì)應(yīng) Office 應(yīng)用否則 ProgID 找不到集合下標(biāo)從 0 開始?worksheets(0)想取第一個(gè)工作表 ? Office 對(duì)象模型的集合索引習(xí)慣從 1 開始寫worksheets(1)用逐格循環(huán)處理大批數(shù)據(jù)? 一個(gè)幾千行的表逐個(gè)單元格讀寫 ? 盡量批量賦值批量場(chǎng)景優(yōu)先考慮openpyxl/pandas用相對(duì)路徑打開文件?Workbooks.Open(data.xlsx)基準(zhǔn)目錄和預(yù)期不符 ? 一律傳絕對(duì)路徑對(duì)不可信文檔自動(dòng)運(yùn)行宏? 腳本對(duì)任意來源的文件直接觸發(fā)宏 ? 只處理可信來源保持 Office 宏安全設(shè)置不要為省事全局關(guān)閉不捕獲 COM 異常? 文件被占用時(shí)腳本直接崩掉沒有提示 ? 捕獲 COM 異常并輸出可讀的錯(cuò)誤信息總結(jié)關(guān)注點(diǎn)結(jié)論所屬庫pywin32的子包需pip install pywin32平臺(tái)僅 Windows前置條件通常要求本機(jī)裝有對(duì)應(yīng) Office入口win32com.client用Dispatch/GetObject創(chuàng)建對(duì)象對(duì)象模型基本對(duì)應(yīng) Office 的 VBA 對(duì)象模型集合索引從 1 開始必做收尾保存/關(guān)閉文檔并顯式Quit()應(yīng)用安全只處理可信文檔不要自動(dòng)運(yùn)行不可信宏把win32com當(dāng)成「用 Python 遙控本機(jī) Office」的工具就夠了能不用就不用只有需要 Office 獨(dú)占的能力真實(shí)計(jì)算、宏、打印、導(dǎo)出 PDF、驅(qū)動(dòng) Outlook時(shí)才上它。用的時(shí)候記住三件事——只能在 Windows 用、要裝 Office、用完必須Quit()——這三個(gè)點(diǎn)覆蓋了新手絕大多數(shù)失敗場(chǎng)景。