最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

如何用 Python 子進(jìn)程關(guān)閉 Excel 自動(dòng)化中的彈窗

 更新時(shí)間:2021年05月07日 15:01:45   作者:crazyhat  
這篇文章主要介紹了如何用 Python 子進(jìn)程關(guān)閉 Excel 自動(dòng)化中的彈窗,幫助大家更好的理解和學(xué)習(xí)使用python,感興趣的朋友可以了解下

利用Python進(jìn)行Excel自動(dòng)化操作的過程中,尤其是涉及VBA時(shí),可能遇到消息框/彈窗(MsgBox)。此時(shí)需要人為響應(yīng),否則代碼卡死直至超時(shí) [^1] [^2]。根本的解決方法是VBA代碼中不要出現(xiàn)類似彈窗,但有時(shí)我們無權(quán)修改被操作的Excel文件,例如這是我們進(jìn)行自動(dòng)化測試的對(duì)象。所以本文記錄從代碼角度解決此類問題的方法。

假想場景

使用xlwings(或者其他自動(dòng)化庫)打開Excel文件test.xlsm,讀取Sheet1!A1單元格內(nèi)容。很簡單的一個(gè)操作:

import xlwings as xw

wb = xw.Book('test.xlsm')
msg = wb.sheets('Sheet1').range('A1').value
print(msg)
wb.close()

然而不幸的是,打開工作簿時(shí)進(jìn)行了熱情的歡迎儀式:

Private Sub Workbook_Open()
    MsgBox "Welcome"
    MsgBox "to open"
    MsgBox "this file."
End Sub

第一個(gè)彈窗Welcome就卡住了Excel,Python代碼相應(yīng)卡死在第一行。

基本思路

主程序中不可能直接處理或者繞過此類問題,也不能奢望有人隨時(shí)蹲守點(diǎn)擊下一步——那就開啟一個(gè)子線程來護(hù)航吧。因此,解決方案是利用子線程監(jiān)聽并隨時(shí)關(guān)閉彈窗,直到主程序圓滿結(jié)束。
解決這個(gè)問題,需要以下兩個(gè)知識(shí)點(diǎn)(基礎(chǔ)知識(shí)請(qǐng)課外學(xué)習(xí)):

  • Python多線程(本文采用threading.Thread)
  • Python界面自動(dòng)化庫(本文涉及pywinauto和pywin32)

pywinauto方案

pywinauto顧名思義是Windows界面自動(dòng)化庫,模擬鼠標(biāo)和鍵盤操作窗體和控件 [^3]。不同于先獲取句柄再獲取屬性的傳統(tǒng)方式,pywinauto的API更加友好和pythonic。例如,兩行代碼搞定窗口捕捉和點(diǎn)擊:

from pywinauto.application import Application

win = Application(backend="win32").connect(title='Microsoft Excel')
win.Dialog.Button.click()

本文采用自定義線程類的方式,啟動(dòng)線程后自動(dòng)執(zhí)行run()函數(shù)來完成上述操作。具體代碼如下,注意構(gòu)造函數(shù)中的兩個(gè)參數(shù):

  • title 需要捕捉的彈窗的標(biāo)題,例如Excel默認(rèn)彈窗的標(biāo)題為Microsoft Excel
  • interval 監(jiān)聽的頻率,即每隔多少秒檢查一次
# listener.py

import time
from threading import Thread, Event
from pywinauto.application import Application


class MsgBoxListener(Thread):

    def __init__(self, title:str, interval:int):
        Thread.__init__(self)
        self._title = title 
        self._interval = interval 
        self._stop_event = Event()   

    def stop(self): self._stop_event.set()

    @property
    def is_running(self): return not self._stop_event.is_set()

    def run(self):
        while self.is_running:
            try:
                time.sleep(self._interval)
                self._close_msgbox()
            except Exception as e:
                print(e, flush=True)


    def _close_msgbox(self):
        '''Close the default Excel MsgBox with title "Microsoft Excel".'''        
        win = Application(backend="win32").connect(title=self._title)
        win.Dialog.Button.click()


if __name__=='__main__':
    t = MsgBoxListener('Microsoft Excel', 3)
    t.start()
    time.sleep(10)
    t.stop()

于是,整個(gè)過程分為三步:

  • 啟動(dòng)子線程監(jiān)聽彈窗
  • 主線程中打開Excel開始自動(dòng)化操作
  • 關(guān)閉子線程
import xlwings as xw
from listener import MsgBoxListener

# start listen thread
listener = MsgBoxListener('Microsoft Excel', 3)
listener.start()

# main process as before
wb = xw.Book('test.xlsm')
msg = wb.sheets('Sheet1').range('A1').value
print(msg)
wb.close()

# stop listener thread
listener.stop()

到此問題基本解決,本地運(yùn)行效果完全達(dá)到預(yù)期。但我的真實(shí)需求是以系統(tǒng)服務(wù)方式在服務(wù)器上進(jìn)行Excel文件自動(dòng)化測試,后續(xù)發(fā)現(xiàn),當(dāng)以系統(tǒng)服務(wù)方式運(yùn)行時(shí),pywinauto竟然捕捉不到彈窗!這或許是pywinauto一個(gè)潛在的問題 [^4]。

win32gui方案

那就只好轉(zhuǎn)向相對(duì)底層的win32gui,所幸完美解決了上述問題。
win32gui是pywin32庫的一部分,所以實(shí)際安裝命令是:

pip install pywin32

整個(gè)方案和前文描述完全一致,只是替換MsgBoxListener類中關(guān)閉彈窗的方法:

import win32gui, win32con

def _close_msgbox(self):
    # find the top window by title
    hwnd = win32gui.FindWindow(None, self._title)
    if not hwnd: return

    # find child button
    h_btn = win32gui.FindWindowEx(hwnd, None,'Button', None)
    if not h_btn: return

    # show text
    text = win32gui.GetWindowText(h_btn)
    print(text)

    # click button        
    win32gui.PostMessage(h_btn, win32con.WM_LBUTTONDOWN, None, None)
    time.sleep(0.2)
    win32gui.PostMessage(h_btn, win32con.WM_LBUTTONUP, None, None)
    time.sleep(0.2)

更一般的方案

更一般地,當(dāng)同時(shí)存在默認(rèn)標(biāo)題和自定義標(biāo)題的彈窗時(shí),就不便于采用標(biāo)題方式進(jìn)行捕捉了。例如

MsgBox "Message with default title.", vbInformation, 
MsgBox "Message with title My App 1", vbInformation, "My App 1"
MsgBox "Message with title My App 2", vbInformation, "My App 2"

那就擴(kuò)大搜索范圍,依次點(diǎn)擊所有包含確定性描述的按鈕(例如OK,Yes,Confirm)來關(guān)閉彈窗。同理替換MsgBoxListener類的_close_msgbox()方法(同時(shí)構(gòu)造函數(shù)中不再需要title參數(shù)):

def _close_msgbox(self):
    '''Click any button ("OK", "Yes" or "Confirm") to close message box.'''
    # get handles of all top windows
    h_windows = []
    win32gui.EnumWindows(lambda hWnd, param: param.append(hWnd), h_windows) 

    # check each window    
    for h_window in h_windows:            
        # get child button with text OK, Yes or Confirm of given window
        h_btn = win32gui.FindWindowEx(h_window, None,'Button', None)
        if not h_btn: continue

        # check button text
        text = win32gui.GetWindowText(h_btn)
        if not text.lower() in ('ok', 'yes', 'confirm'): continue

        # click button
        win32gui.PostMessage(h_btn, win32con.WM_LBUTTONDOWN, None, None)
        time.sleep(0.2)
        win32gui.PostMessage(h_btn, win32con.WM_LBUTTONUP, None, None)
        time.sleep(0.2)

最后,實(shí)例演示結(jié)束全文,以后再也不用擔(dān)心意外彈窗了。

以上就是如何用 Python 子進(jìn)程關(guān)閉 Excel 自動(dòng)化中的彈窗的詳細(xì)內(nèi)容,更多關(guān)于Python 子進(jìn)程關(guān)閉 Excel 彈窗的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • k-means 聚類算法與Python實(shí)現(xiàn)代碼

    k-means 聚類算法與Python實(shí)現(xiàn)代碼

    這篇文章主要介紹了k-means 聚類算法與Python實(shí)現(xiàn)代碼,本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-06-06
  • 夯實(shí)基礎(chǔ)python集合的應(yīng)用場景及字符串定義和表示

    夯實(shí)基礎(chǔ)python集合的應(yīng)用場景及字符串定義和表示

    這篇文章主要為大家介紹了python集合的應(yīng)用場景及字符串定義和表示,來幫大家夯實(shí)基礎(chǔ),有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2023-10-10
  • Python使用matplotlib的pie函數(shù)繪制餅狀圖功能示例

    Python使用matplotlib的pie函數(shù)繪制餅狀圖功能示例

    這篇文章主要介紹了Python使用matplotlib的pie函數(shù)繪制餅狀圖功能,結(jié)合實(shí)例形式分析了Python使用matplotlib的pie函數(shù)進(jìn)行餅狀圖繪制的具體操作技巧,注釋中對(duì)pie函數(shù)的用法進(jìn)行了詳細(xì)的說明,便于理解,需要的朋友可以參考下
    2018-01-01
  • 詳解Django緩存處理中Vary頭部的使用

    詳解Django緩存處理中Vary頭部的使用

    這篇文章主要介紹了詳解Django緩存處理中Vary頭部的使用,Django是最具人氣的Python web開發(fā)框架,需要的朋友可以參考下
    2015-07-07
  • Python三十行代碼實(shí)現(xiàn)簡單人臉識(shí)別的示例代碼

    Python三十行代碼實(shí)現(xiàn)簡單人臉識(shí)別的示例代碼

    這篇文章主要介紹了Python三十行代碼實(shí)現(xiàn)簡單人臉識(shí)別的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • Django models文件模型變更錯(cuò)誤解決

    Django models文件模型變更錯(cuò)誤解決

    這篇文章主要介紹了Django models文件模型變更錯(cuò)誤解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-05-05
  • Python實(shí)現(xiàn)刪除文件中含“指定內(nèi)容”的行示例

    Python實(shí)現(xiàn)刪除文件中含“指定內(nèi)容”的行示例

    這篇文章主要介紹了Python實(shí)現(xiàn)刪除文件中含“指定內(nèi)容”的行功能,涉及Python針對(duì)文件讀取及字符串遍歷、判斷等相關(guān)操作技巧,需要的朋友可以參考下
    2017-06-06
  • Python簡單實(shí)現(xiàn)socket信息發(fā)送與監(jiān)聽功能示例

    Python簡單實(shí)現(xiàn)socket信息發(fā)送與監(jiān)聽功能示例

    這篇文章主要介紹了Python簡單實(shí)現(xiàn)socket信息發(fā)送與監(jiān)聽功能,結(jié)合實(shí)例形式分析了Python基于socket構(gòu)建客戶端與服務(wù)器端通信相關(guān)操作技巧,需要的朋友可以參考下
    2018-01-01
  • Python使用OpenCV庫實(shí)現(xiàn)圖像幾何變化

    Python使用OpenCV庫實(shí)現(xiàn)圖像幾何變化

    幾何變換是通過數(shù)學(xué)變換將圖像的像素從一個(gè)位置映射到另一個(gè)位置的過程,在圖像處理領(lǐng)域,幾何變換是一個(gè)非常重要的操作,它可以改變圖像的位置、大小、方向或形狀,本文將介紹如何利用 Python 的 OpenCV 庫實(shí)現(xiàn)圖像的幾何變換,需要的朋友可以參考下
    2024-12-12
  • Python中使用filter過濾列表的一個(gè)小技巧分享

    Python中使用filter過濾列表的一個(gè)小技巧分享

    這篇文章主要介紹了Python中使用filter過濾列表的一個(gè)小技巧分享,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-05-05

最新評(píng)論

黄浦区| 和硕县| 汶川县| 瑞金市| 金堂县| 德庆县| 重庆市| 成安县| 科技| 东阳市| 滦南县| 昆山市| 交城县| 泰安市| 龙门县| 鸡泽县| 孝昌县| 平陆县| 兴义市| 棋牌| 山阳县| 贵溪市| 金堂县| 喀喇沁旗| 荔波县| 文成县| 武冈市| 银川市| 沁源县| 吴江市| 罗源县| 封丘县| 嘉禾县| 垫江县| 杂多县| 伊通| 山阳县| 武威市| 库尔勒市| 霍林郭勒市| 琼海市|