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

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

SAP下载报表速度慢?为啥你不试试python多线程的更多相关文章

  1. 启动运行下载gradle速度太慢,手动添加

    启动运行下载gradle速度太慢,并且容易卡死(感谢群友ˋ狠ㄨ得意提供支持)---国内网络访问地址 我们经常运行项目的时候会需要进行下载gradle,不过由于网络或者和谐的问题经常下载需要花很长时间或 ...

  2. Python3 解决windows里PIP下载安装速度慢

    直接保存为xxx.py运行即可 自动在用户文件夹创建pip文件夹,并创建配置文件:pip.ini 从此告别pip install XXXX 下载模块速度超级慢的问题! # -*- coding: ut ...

  3. python多线程爬虫+批量下载斗图啦图片项目(关注、持续更新)

    python多线程爬虫项目() 爬取目标:斗图啦(起始url:http://www.doutula.com/photo/list/?page=1) 爬取内容:斗图啦全网图片 使用工具:requests ...

  4. python多线程批量下载远程图片

    python多线程使用场景:多线程采集, 以及性能测试等 . 数据库驱动类-简单封装下 mysqlDriver.py #!/usr/bin/python3 #-*- coding: utf-8 -*- ...

  5. 以下三种下载方式有什么不同?如何用python模拟下载器下载?

    问题始于一个链接https://i1.pixiv.net/img-zip-...这个链接在浏览器打开,会直接下载一个不完整的zip文件 但是,使用下载器下载却是完整文件 而当我尝试使用python下载 ...

  6. SAP 快速报表

    快速报表,这个名字不知道是不是第一个用,不过以这种方式做的报表,速度确实挺快的,应该比QUERY快,还简单 T-CODE:SQVI 进入界面后,输入一个报表名称,点击新建,这时候可以选择,单表查询,链 ...

  7. iOS开发下载文件速度计算

    当我们写下载界面的时候,需要向用户展示每秒下载多少KB,这个时候就需要计算速度.如下: 我用的是AFNetworking来做下载的,我们拿AFHTTPRequestOperation来举列,AFHTT ...

  8. GitHub克隆下载代码速度慢解决办法

    这几天克隆下载GitHub代码奇慢无比,网上搜索了一下解决方案有些不太完整,自己试验出了比较完整的解决方式: 1.在hosts文件里追加以下内容(IP需要替换掉),以下几个域名一个都不要少,有些文章只 ...

  9. WPF SAP水晶报表例子和打包Setup

    <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x=" ...

随机推荐

  1. 【LeetCode】127. Word Ladder 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址: https://leetcode.com/problems/word-lad ...

  2. The more, The Better(hdu1561)

    The more, The Better Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Oth ...

  3. Nginx 简单配置反向代理

    nginx 配置反向代理,转发请求到另一个域名 在server中加入 location /${alias} { proxy_buffer_size 128k; proxy_buffers 32 32k ...

  4. spring练习,在Eclipse搭建的Spring开发环境中,使用set注入方式,实现对象的依赖关系,通过ClassPathXmlApplicationContext实体类获取Bean对象

    相关 知识 >>> 相关 练习 >>> 实现要求: 在Eclipse搭建的Spring开发环境中,使用set注入方式,实现对象的依赖关系,通过ClassPathXm ...

  5. gPRC基本介绍

    1.说明 gRPC英文全名为Google Remote Procedure Call, 即Google远程过程调用, 是Google发布的一个高性能.通用的开源RPC框架, 2.gRPC定义 gRPC ...

  6. frontend-maven-plugin插件问题解决

    1.插件介绍 frontend-maven-plugin为项目本地下载/安装Node和NPM,运行npm install命令 . 它适用于Windows,OS X和Linux. 这个插件也可以下载No ...

  7. C语言 Make命令教程

    make只是一个根据指定的Shell命令进行构建的工具 在linux和unix中,有一个强大的使用程序,叫make,可以用它来管理多模块程序的编译和链接,直至生成可执行文件 make使用程序读取一个说 ...

  8. MySQL存储过程入门基础

    创建存储过程无参语法: delimiter // create procedure 函数名() begin 业务逻辑 end // call 函数名() 通过函数名调用存储过程 创建存储过程有参与法: ...

  9. 自动化怎么判断anndroid.listview是否包含某个指定的元素或内容

    做自动化的时候,定位元素时,会发现整屏的内容都是放在一个列表,在多层嵌套其他控件组成 如柠檬班的题库,里面会有很多分类 那么在做自动化的时候,怎么判断页面有没有包含指定的分类呢? 整体思路: 1.找到 ...

  10. Typescript Record的用法

    Record<Keys,Type> 构造一个对象类型,其属性key是Keys,属性value是Tpye.被用于映射一个类型的属性到另一个类型 interface CatInfo { age ...