那里。
我每天在 SAP GUI 中使用 Python 进行两次提取,这会消耗大量时间,因此必须更快地完成。因此,我正在尝试并行运行两个事务来解决这个问题。
我陷入了这里发生的同样问题使用Python在SAP GUI中进行多重处理,但我找不到解决这个问题的方法。基本上,当我尝试使用 Python 多处理库访问 SAP GUI 时,这是一个问题,并且内部模块之一尝试腌制 SAP GUI 会话对象。
这是错误:TypeError:无法腌制“PyIDispatch”对象
我正在尝试访问 SAP GUI 版本 740 以同时提取两个交易报告,就像我的朋友一样
上面我无法使用 RFC 工具。我知道这是不可维护的解决方案,但这将是这个问题的临时解决方案。
我的代码中有两个文件 - sap_novo:
import time, win32com.client
from subprocess import Popen
class SAP:
def __init__(self, site): # Função que inicia a classe SAP
self.path = 'C:\\Program Files (x86)\\SAP\\FrontEnd\\SAPgui\\saplgpad.exe'
self.site = site
self.SSO = SSO
self.con = None
self.appl = None
self.sap_gui = None
self.session = None
@property
def session(self):
return self._session
@session.setter
def session(self, value):
self._session = value
def connectToSAP(self):
Popen(self.path)
time.sleep(15)
SapGui = win32com.client.GetObject("SAPGUI")
Appl = SapGui.GetScriptingEngine
con = Appl.OpenConnection(self.site, True)
self.session = con.Children(0)
self.con = Appl.Connections(0)
主要
from multiprocess import Process
import sap_novo
import dill
def CX34(con_base, id_session):
sap_session = con_base.Sessions(id_session)
sap_session.findById("wnd[0]").maximize()
sap_session.findById("wnd[0]/tbar[0]/okcd").text = "cx34"
sap_session.findById("wnd[0]").sendVKey(0)
def FS10N(con_base, id_session):
sap_session = con_base.Sessions(id_session)
sap_session.findById("wnd[0]").maximize()
sap_session.findById("wnd[0]/tbar[0]/okcd").text = "FS10N"
sap_session.findById("wnd[0]").sendVKey(0)
def run_parallel(connection):
p1 = Process(target=CX34, args=(connection, 0))
p2 = Process(target=FS10N, args=(connection, 1))
p1.start()
p2.start()
p1.join()
p2.join()
def main():
sap_obj = sap_novo.SAP('Environment')
sap_obj.connectToSAP()
sap_obj.checkLogin(sap_obj.session,"wnd[1]")
run_parallel(sap_obj.con)
if __name__ == '__main__':
main()
我使用 dill 包来了解使用它会发生什么
dill.detect.trace(True)
dill.pickles(sap_obj.session)
print(dill.dumps(sap_obj.session))
,我得到:
T4: \<class 'win32com.client.CDispatch'\>
# T4 \[32 B\]
┬ D2: \<dict object at 0x20ba608a500\>
┬ T4: \<class 'win32com.client.CDispatch'\>
└ # T4 \[32 B\]
┬ D2: \<dict object at 0x20ba608a500\>
然后,它看起来像是 win32com.client.CDispatch 对象中序列化/pickle 的问题。
有人可以帮我吗?
谢谢!!
伙计们。
我使用 python 线程包实现了我的目标。我无法使用多进程使其工作。
基本上,我正在创建两个线程,每个事务代码一个,并为每个函数传递一个会话 ID。
但是,要使这项工作有效,需要一个中间步骤。我必须使用 pythoncom 库在线程之间传递会话对象,因为在 python 中同时使用 COM 对象和线程存在一些限制。本主题帮助我做到这一点使用 win32com 进行多线程处理。
从这个意义上说,我必须创建两个函数来序列化和反序列化会话对象。
def serializeSessions(sap_sessions):
sessions = []
for session in sap_sessions:
sessions.append(pythoncom.CoMarshalInterThreadInterfaceInStream(pythoncom.IID_IDispatch,
session))
return sessions
def deserializeSession(session_id):
pythoncom.CoInitialize()
#
# Get instance from the id
session = win32com.client.Dispatch(
pythoncom.CoGetInterfaceAndReleaseStream(session_id, pythoncom.IID_IDispatch)
)
return session
这样,我在实例化线程之前进行序列化,然后传递序列化的会话对象并在事务函数内运行反序列化。
非常感谢您的分享,我完全按照您所说的进行了测试,第一次就成功了,现在有了这个概念,我将能够加快我的 RPA 速度。
from sap import SAPConnector
import threading
import pythoncom
import win32com.client
SAP = SAPConnector()
sap_sessions = SAP.session(total_sessions=6)
def serializeSessions(sap_sessions):
serial_sessions = []
for session in sap_sessions:
serial_sessions.append(
pythoncom.CoMarshalInterThreadInterfaceInStream(pythoncom.IID_IDispatch,session)
)
return serial_sessions
def deserializeSession(serial_session):
pythoncom.CoInitialize()
session = win32com.client.Dispatch(
pythoncom.CoGetInterfaceAndReleaseStream(serial_session, pythoncom.IID_IDispatch)
)
return session
def xk03(serial_session):
session = deserializeSession(serial_session)
session.findById("wnd[0]/tbar[0]/okcd").text = "/nxk03"
session.findById("wnd[0]").sendVKey(0)
def me21n(serial_session):
session = deserializeSession(serial_session)
session.findById("wnd[0]/tbar[0]/okcd").text = "/nme21n"
session.findById("wnd[0]").sendVKey(0)
def me33k(serial_session):
session = deserializeSession(serial_session)
session.findById("wnd[0]/tbar[0]/okcd").text = "/nme33k"
session.findById("wnd[0]").sendVKey(0)
def xk03(serial_session):
session = deserializeSession(serial_session)
session.findById("wnd[0]/tbar[0]/okcd").text = "/nxk03"
session.findById("wnd[0]").sendVKey(0)
def ie03(serial_session):
session = deserializeSession(serial_session)
session.findById("wnd[0]/tbar[0]/okcd").text = "/nie03"
session.findById("wnd[0]").sendVKey(0)
def ml81n(serial_session):
session = deserializeSession(serial_session)
session.findById("wnd[0]/tbar[0]/okcd").text = "/nml81n"
session.findById("wnd[0]").sendVKey(0)
def run_parallel(list_sessions):
t1 = threading.Thread(target=xk03, args=(list_sessions[0], ))
t2 = threading.Thread(target=me21n, args=(list_sessions[1], ))
t3 = threading.Thread(target=me33k, args=(list_sessions[2], ))
t4 = threading.Thread(target=xk03, args=(list_sessions[3], ))
t5 = threading.Thread(target=ie03, args=(list_sessions[4], ))
t6 = threading.Thread(target=ml81n, args=(list_sessions[5], ))
t1.start()
t2.start()
t3.start()
t4.start()
t5.start()
t6.start()
t1.join()
t2.join()
t3.join()
t4.join()
t5.join()
t6.join()
list_serial_sessions = serializeSessions(sap_sessions)
run_parallel(list_serial_sessions)