[英]Multiprocessing in SAP using Python
TypeError: cannot pickle 'PyIDispatch' object
和
PermissionError: [WinError 5] Acess denied
到目前为止,我得到的是打开两个 windows(创建两个 SAP 会话)并在不同的 windows 中访问事务,但一个接一个,换句话说,不是同时访问。
该测试程序由 3 个单独的脚本组成:
脚本:
创建连接.py
from subprocess import Popen import time from win32com.client import GetObject class Sap: def __init__(self, sap_env, user_id, user_password, language="EN", newSession=False, connectBy=2): self.sap_file = "C:\\Program Files (x86)\\SAP\\FrontEnd\\SapGui" +\ "\\saplogon.exe" self.sap_env = sap_env self.user_id = user_id self.user_password = user_password self.language = language self.connectBy = connectBy self.newSession = newSession def __get_sap_gui__(self): try: return GetObject('SAPGUI').GetScriptingEngine except: time.sleep(0.5) return self.__get_sap_gui__() def get_sap_connection(self): if self.connectBy == 3: Popen(self.sap_file + ' ' + self.sap_env) sapGui = self.__get_sap_gui__() conn = sapGui.Connections(0) timeout = 10 while conn.Sessions.Count == 0 and timeout: time.sleep(1) timeout -= 1 if timeout == 0: raise Exception("Fail to connect") else: Popen(self.sap_file) sapGui = self.__get_sap_gui__() conn = None if self.connectBy == 1: if sapGui.Connections.Count > 0: # it's not good, I'll fix this later for conn in sapGui.Connections: if conn.Description == self.sap_env: break if not conn: conn = sapGui.OpenConnection(self.sap_env) else: if sapGui.Connections.Count > 0: for conn in sapGui.Connections: if self.sap_env in conn.ConnectionString: break if not conn: conn = sapGui.OpenConnectionByConnectionString(self.sap_env) return conn def get_sap_session(self, conn): if self.newSession: numSessions = conn.Sessions.Count + 1 conn.Sessions(0).createsession() while conn.Sessions.Count < numSessions: pass session = conn.Sessions(numSessions-1) else: session = conn.Sessions(0) if session.findById('wnd[0]/sbar').text.startswith('SNC logon'): session.findById('wnd[0]/usr/txtRSYST-LANGU').text = self.language session.findById('wnd[0]').sendVKey(0) session.findById('wnd[0]').sendVKey(0) elif session.Info.User == '': session.findById('wnd[0]/usr/txtRSYST-BNAME').text = self.user_id session.findById('wnd[0]/usr/pwdRSYST-BCODE').text =\ self.user_password session.findById('wnd[0]/usr/txtRSYST-LANGU').text = self.language session.findById('wnd[0]').sendVKey(0) session.findById('wnd[0]').maximize() return session
操纵SAP.py
from createconnection import Sap class QuerySap(Sap): def __init__(self, sap_env, user_id, user_password, language): super().__init__(sap_env, user_id, user_password, language=language) self.connection = self.get_sap_connection() self.session = self.get_sap_session(self.connection) self.new_session = None def open_new_windows(self): self.connection.Sessions(0).createsession() self.connection.Sessions(0).createsession() self.new_session = self.connection.Sessions(1) @property def sess1(self): return self.session @property def sess2(self): return self.new_session
主文件
from manipulatesap import QuerySap from multiprocessing import Pool, Process from time import sleep def goto_trasaction(session, transacion): session.findById("wnd[0]/tbar[0]/okcd").text = transacion session.findById("wnd[0]").sendVKey(0) sleep(5) def sap_interface_multi_process(usr, pw, env): sap_nav = QuerySap(sap_env=env, user_id=usr,user_password=pw, language="PT") sap_nav.open_new_windows() session1 = sap_nav.sess1 session2 = sap_nav.sess2 p1 = Process(target=goto_trasaction, args=(session1, "TRANSACION A")) p2 = Process(target=goto_trasaction, args=(session2, "TRANSACTION B")) p1.start() p2.start() p1.join() p1.join() def main(): print(">>> Start") sap_env = "string_for_connection" sap_interface_multi_process("usr_id", "usr_pw", sap_env) print(">>> Finish") if __name__ == "__main__": main()
你们能帮我找到我缺少的东西和我应该做什么吗?
非常感谢
经过一段时间的假期,我终于得到了解决方案。
但是我不得不重构我的很多代码。
我所做的是将 sap class 实例化为 object 并将此 object 传递给将并行执行的 ZC1C425268E68385D1AB6674。 在这个 function 内部,我使用 sap class 方法创建连接并创建 session。
这是我的解决方案。 不漂亮但有效:
from Modules.Sap.sapinit import Sap
def create_sap_session(sap_obj, extra_num_sessions):
sap_conn = sap_obj.get_sap_connection()
sap_obj.get_sap_session(sap_conn)
if extra_num_sessions < 1:
return
for _ in range(extra_num_sessions):
sap_conn.Sessions(0).createsession()
return
def parallel_sap_query(sap_obj, sessions_num, transaction):
sap_conn = sap_obj.get_sap_connection()
sap_session = sap_conn.Sessions(sessions_num)
session.findById("wnd[0]/tbar[0]/okcd").text = transaction
session.findById("wnd[0]").sendVKey(0)
def execute_cancellations(sap_obj):
create_sap_session(sap_obj, 2)
sleep(3)
p1 = Process(target=parallel_sap_query, args=(sap_obj, 0, "A", ))
p2 = Process(target=parallel_sap_query, args=(sap_obj, 1, "B", ))
p3 = Process(target=parallel_sap_query, args=(sap_obj, 2, "C", ))
p1.start()
p2.start()
p3.start()
p1.join()
p2.join()
p3.join()
close_sap_sessions(sap_obj, 2, 1, 0)
def close_sap_sessions(sap_obj, *sessions):
sap_conn = sap_obj.get_sap_connection()
for session in sessions:
sap_session = sap_conn.Sessions(session)
sap_session.findById("wnd[0]").close()
sap_session.findById("wnd[1]/usr/btnSPOP-OPTION1").press()
def main():
sap_obj = Sap(sap_env, sap_id, sap_pw, "PT")
execute_cancellations(sap_obj)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.