SAP下载报表速度慢?为啥你不试试python多线程

博客 分享
0 298
张三
张三 2022-01-28 16:54:40
悬赏:0 积分 收藏

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个自动化机器人在同时帮小爬分担枯燥的数据下载工作,幸福感瞬间拉满!!!

  有任何疑问,欢迎评论区积极留言,同时也欢迎扫码关注我的公众号,获取更多爬虫、数据分析的知识!

 

posted @ 2022-01-28 15:53 NewJune 阅读(46) 评论(0) 编辑 收藏 举报
回帖
    张三

    张三 (王者 段位)

    821 积分 (2)粉丝 (41)源码

     

    温馨提示

    亦奇源码

    最新会员