繁体   English   中英

使用 Python 在 SAP 中进行多处理

[英]Multiprocessing in SAP using Python


我的 SAP 非常旧,我无法使用它进行 API 调用。 所以,我必须操纵 SAP 的 GUI 来完成我的工作。
我正在尝试使用 Python 在两个不同的 windows 中同时访问两个 SAP 事务。
为此,我使用了以下库:pywin32、subprocess 和 multiprocessing。

但我收到以下错误:
 TypeError: cannot pickle 'PyIDispatch' object

PermissionError: [WinError 5] Acess denied

到目前为止,我得到的是打开两个 windows(创建两个 SAP 会话)并在不同的 windows 中访问事务,但一个接一个,换句话说,不是同时访问。

该测试程序由 3 个单独的脚本组成:

  • 一个有 class 来创建连接,创建第一个 session 并登录到帐户。
  • 第二个 class 是“操纵” SAP
  • 最后一个是主脚本。

脚本:
创建连接.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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM