SAP下載報表速度慢?爲啥你不試試python多線程

  由於SAP系統自身原因,或者公司內部ABAP代碼的算法效率不高,我們經常遇到,手工執行某個事務代碼下載某個報表會非常耗時,小爬曾見過公司某個自開發的報表,單家公司的數據下載超過半小時。如果我們剛好接到一個自動化需求:批量下載N個公司的某些報表數據,即使我們用python腳本實現了該場景的自動化,效率依然不高。

 

  或許我們可以嘗試python的多線程技術來加速。這應該是個好主意,現在小爬就帶着大家往多線程這個方向思考。

  SAP GUI的會話數量一般都有限制,各個公司的SAP策略或有不同,在小爬所在的公司,SAP GUI客戶端允許的會話數不超過6,我們不妨用多個會話分別去下載數據。小爬遇到的場景是:有N家公司,分別進入4個事務代碼下載四張不同的表,這四張表的導出速度各有不同,有的較快,有的極慢。

方案一:我們啓用四個sap會話,分別下載這四張表,每次參數中傳入不同的公司代碼;

方案二:我們開啓最大SAP會話數6,每個會話都執行一些公司代碼,也都會下載到這四張表。

  仔細思考後不難發現,方案二可以將下載速度最大化。方案一中各個會話對應的報表下載速度各不相同,最終速度受最慢的那個影響,而且它只能根據四張報表來啓用四個會話線程;而方案一,則可以同時開啓六個SAP會話線程,且每個會話下都會下載這四張表,無形中,避免了”一個會話在苦戰,其它會話全圍觀“的尷尬局面。

  具體到代碼層面,我們需要批量創建多個sap會話,新建一個全局的任務隊列companyQ,每個sap會話獨自不停去隊列中取任務(下載需要的參數),驅動各自負責的SAP會話來完成數據的下載,當隊列中所有任務都完成了,意味着線程結束。等以上思路都琢磨明白了,代碼該怎麼寫就不再是一個問題了。

第一步:定義連接sap的方法,並自動開啓N個session會話

第二部:定義下載SAP數據的方法

第三步:開啓多個線程,分別調用同一個方法,傳入不同session的index作爲參數,實現對多個會話的自動化控制

def connect_SAP(maxSessionNum):
    '''連接SAP,並創建maxSessionNum個session會話,返回session列表(含session索引)'''
    SapGuiAuto = win32com.client.GetObject("SAPGUI")
    application = SapGuiAuto.GetScriptingEngine
    connection = application.Children(0)
    indexSessions=[]
    session=connection.Children(0)
    cnt=connection.Children.Count
    if cnt<maxSessionNum:
        for _ in range(maxSessionNum-cnt):
            session.Createsession()
            sleep(0.5)
    sleep(2)
    for index,session in enumerate(connection.Children):
        indexSessions.append([index,session])
    SapGuiAuto=None
    application=None
    connection=None
    session=None
    return indexSessions

def exportSapData(sessionIndex):
    '''給定公司代碼,期間,依次導出應收社保、公積金,應付社保、公積金報表數據'''
    pythoncom.CoInitialize()
    SapGuiAuto = win32com.client.GetObject("SAPGUI")
    application = SapGuiAuto.GetScriptingEngine
    connection = application.Children(0)
    session=connection.Children(sessionIndex)

    '''輸入zhr054,導出HR社保往來掛賬應付公積金明細表'''
    session.findById("wnd[0]").iconify() 
    unfinishedNum=companyQ.unfinished_tasks
    while True:
        lk.acquire()
        if not companyQ.empty():
            companyCode=companyQ.get(block=False)
        else:
            lk.release()
            break
        lk.release()
        downloadFunc(companyCode,reportPeriod)

  下面的代碼便演示瞭如何藉助python多線程技術,針對每個線程,傳入的參數就是session的索引號(0-6),最終把他們分別啓動起來~

connect_SAP(maxSessionNum=5)
sleep(3)
threads = []
for i in range(6):
    threads.append(threading.Thread(target=exportSapData,args=(i,)))
for companyCode in companies:
    companyQ.put(companyCode)
for t in threads:
    t.setDaemon(True)
    t.start()
for t in threads:
    t.join()
 
print ("all over %s" %ctime())
endtime = datetime.datetime.now()
secs = (endtime - starttime).seconds
minutes = secs // 60
second = secs % 60  
timeStr = str(minutes) + '分鐘' + str(second) + "秒"
root=tk.Tk()
root.withdraw()
tkinter.messagebox.showinfo("信息",f"已完成所有數據下載,運行時間爲:{timeStr}")

 

  以上,就是小爬利用python多線程來驅動sap多個會話進行特定自動化操作的主要過程。基於這一波操作,整個下載效率可以提升4-6倍。那一刻,彷彿有6個自動化機器人在同時幫小爬分擔枯燥的數據下載工作,幸福感瞬間拉滿!!!

  有任何疑問,歡迎評論區積極留言,同時也歡迎掃碼關注我的公衆號,獲取更多爬蟲、數據分析的知識!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章