Hello community,

in the last time I presented a way to integrate a script language inside ABAP. To demonstrate that the these procedures work with other scripting languages too, I take the same methods and use it with Python language. Also I will show that it is possible to use the same ways with more volumminous environments. So I contain a complete Python environment inside ABAP and unpack it at the runtime of my ABAP program and in the context of the ABAP program I create a Python script an use it inside ABAP.

Steps

  1. Downloading of Python 2.7.5 from http://www.python.org/.
  2. Installation of Python in the standard default directory C:\Python27.
  3. Copying of python27.dll from c:\Windows\system32 into C:\Python27.
  4. Creating of a multi part RAR archive with a part size of max. 8,000,000 bytes. So I get three RAR archives.
  5. Creating of three ABAP function modules with BinFile2ABAP which contains these RAR archives.
  6. Creating of three function groups and upload of the function modules inside this groups.
    Hint: It is not possible to store more than 65,535 literals in one function group. So it is necessary to create for each function module its own function group.
  7. Upload of zScripXDll function module from here. It contains ScriptX ActiveX library which builds the bridge between ABAP and the scripting language.

With these preparations you build the possibility to use Python inside ABAP.

 

ABAP Test Program

"-Begin-----------------------------------------------------------------
  Program ZSCRIPTX.

    "-Constants---------------------------------------------------------
      Constants CrLf(2) Type c Value %_CR_LF.
      Constants SW_SHOWNORMAL Type i Value 1.

    "-Variables---------------------------------------------------------
      Data oScriptX Type OLE2_OBJECT.
      Data Buffer Type String Value ''.
      Data WorkDir Type String Value ''.
      Data FileName Type String Value ''.
      Data rc Type i Value 0.
      Data hFileMap Type i Value 0.
      Data RetCode Type String Value ''.

    "-Macros------------------------------------------------------------
      Define _.
        Concatenate Buffer &1 CrLf Into Buffer.
      End-Of-Definition.

      Define Flush.
        Call Function 'AC_SYSTEM_FLUSH' Exceptions Others = 1.
      End-Of-Definition.

    "-Main--------------------------------------------------------------
      Create Object oScriptX 'ScriptX'.

      If sy-subrc <> 0 Or  oScriptX-Handle = 0 Or oScriptX-Type <> 'OLE2'.
        Call Function 'ZSCRIPTXDLL'.
        Create Object oScriptX 'ScriptX'.
      EndIf.

      If sy-subrc = 0 And oScriptX-Handle > 0 And oScriptX-Type = 'OLE2'.
        Call Method Of oScriptX 'About'.
        Flush.

        "-Create multi part archive files-------------------------------
          Call Function 'ZPYTHON27PART1RAR'.
          Call Function 'ZPYTHON27PART2RAR'.
          Call Function 'ZPYTHON27PART3RAR'.

        "-Unpack archive------------------------------------------------
          Call Method Of oScriptX 'Unrar' Exporting
            #1 = 'Python27.part1.rar'.
          Flush.

        "-Delete multi part archive files-------------------------------
          Call Method Of oScriptX 'DeleteFile' Exporting
            #1 = 'Python27.part1.rar'.
          Call Method Of oScriptX 'DeleteFile' Exporting
            #1 = 'Python27.part2.rar'.
          Call Method Of oScriptX 'DeleteFile' Exporting
            #1 = 'Python27.part3.rar'.
          Flush.

        Call Method Of oScriptX 'FileMapCreate' = hFileMap
          Exporting #1 = 'SAP001' #2 = 64.
        Flush.

        If hFileMap <> 0.

"-Python Script begin---------------------------------------------------

  "-External libraries--------------------------------------------------
_ 'import ctypes'.
_ 'import sys'.

  "-Constants-----------------------------------------------------------
_ 'FILE_MAP_ALL_ACCESS = 30'.

  "-Main----------------------------------------------------------------
_ 'print "Python version ", sys.version'.
_ 'print "Hello World from Python"'.
_ 'var_inp = raw_input("Enter something: ")'.
_ 'print "You entered: ", var_inp'.

  "-Transfer the input to the memory map file---------------------------
_ 'hMMF = ctypes.windll.kernel32.OpenFileMappingA(FILE_MAP_ALL_ACCESS, \'.
_ '  0, "SAP001")'.
_ 'if hMMF <> 0:'.
_ '  buffer = ctypes.windll.kernel32.MapViewOfFile(hMMF, \'.
_ '    FILE_MAP_ALL_ACCESS, 0, 0, 0)'.
_ '  if buffer <> 0:'.
_ '    ctypes.cdll.msvcrt.strcpy(buffer, var_inp)'.
_ '    rc = ctypes.windll.kernel32.UnmapViewOfFile(buffer)'.
_ '  rc = ctypes.windll.kernel32.CloseHandle(hMMF)'.

_ 'raw_input("Press any key...")'.


"-Python Script end-----------------------------------------------------

          "-Get SAP GUIs work directory---------------------------------
            Call Method cl_gui_frontend_services=>get_sapgui_workdir
              Changing SAPWORKDIR = WorkDir Exceptions Others = 1.

          "-Create Python script file-----------------------------------
            Concatenate WorkDir '\Python27\Test.py' Into FileName.
            Call Method Of oScriptX 'WriteFile' Exporting #1 = FileName
              #2 = Buffer.
            Flush.

          "-Execute Python script---------------------------------------
            Call Method Of oScriptX 'Shell' = rc Exporting
              #1 = 'Python27\python.exe' #2 = 'Python27\Test.py'
              #3 = SW_SHOWNORMAL #4 = 1.
            Flush.

          "-Read the input from the memory map file---------------------
            Call Method Of oScriptX 'FileMapRead' = RetCode
              Exporting #1 = 'SAP001' #2 = 64.
            Flush.

          "-Destroy memory map file-------------------------------------
            Call Method Of oScriptX 'FileMapClose' = rc
              Exporting #1 = hFileMap.
            Flush.

          "-Delete Python environment-----------------------------------
            Call Method Of oScriptX 'DeleteDirectory' Exporting
              #1 = 'Python27'.
            Flush.

          "-Write the content of the memory map file--------------------
            Write: / RetCode.

        EndIf.

        Free Object oScriptX.
      EndIf.

"-End-------------------------------------------------------------------

 

zPython.jpg

 

Benefits

  1. Zero install, only copy.
  2. No admin rights necessary.
  3. All activities are in the user space only.
  4. These methods works perfect in protected and restricted environments.
  5. ABAP function modules contains all you need.
  6. No admin activities necessary. All you need you get with a simple call of an ABAP function module.

 

Addendum

2014/11/19 – Look here for an update.

 

Good scripting.

Cheers
Stefan

To report this post you need to login first.

17 Comments

You must be Logged on to comment or reply to a post.

  1. tanaya amdekar

    Hi Stefan,

    Thanks for the post.

    “Create Object oScriptX ‘ScriptX'” is returning exception 2, is it related to local directory ?

    Also, can the connection of Python with ABAP stay active for more than 1 hour ? We are trying to use Python for complex mathematical calculation of matrices, which will definitely take more time than usual computation.

    Thanks in advance….Tanaya

    (0) 
    1. Stefan Schnell Post author

      Hello Tanaya,

      thanks for your reply.

      I never tried to hold a connect between an ABAP program and an external process on the presentation server over this long period. But it is an interesting question.

      So I did a little experimenting and detected that long-running calls in this case must always include an event-processing, otherwise you can not work with your SAP Logon, it is blocked. In consideration of this fact it is possible to run long time processes.

      Cheers

      Stefan

      (0) 
      1. tanaya amdekar

        Sorry, my screen dint refresh your reply, so edited my earlier comment.

        I am able to create multi part archive.

        I am trying to run your mentioned example but it is failing.

        “Create Object oScriptX ‘ScriptX'” is returning exception 2, is it related to local directory ?

        About long connection, I am planning to run it in background job. I shall update its success, once I am able to create OLE object.

        Thanks..Tanaya

        (0) 
        1. Stefan Schnell Post author

          Hallo Tanaya,

          I am afraid you can’t run this kind of process as background job, because the command Create Object – OLE needs a dialog process to communicate between the ABAP program on the backend and the Python process via ScriptX on the frontend.

          To check out the functionality register ScriptX on your presentation server enter from the command line

          rundll32 ScriptX.dll,RegisterServer %cd%

          You should see the following dialog after a successful registration.

          Dialog1.jpg

          ScriptX is a 32-bit library. If you are working in a 64-bit environment, be sure to open a 32-bit console.

          Try this VBScript to check the ScriptX installation:

          Set oScriptX = CreateObject("ScriptX")
          If IsObject(oScriptX) Then
            rc = oScriptX.MsgBox("Hello World", "ScriptX", 0)
            Set oScriptX = Nothing
          End If

          Be sure to execute this program also from 32-bit.

          Let us know the results.

          Cheers

          Stefan

          (0) 
          1. tanaya amdekar

            Hi Stefan,

            Thanks for the statement “To check out the functionality register ScriptX”.

            You are right, I am working in 64-bit environment.

            I am still exploring ways to open 32-bit console.

            Please share any information on how to run ABAP program in 64-bit environment with 32-bit ScriptX library?

            Thanks……Tanaya

            (0) 
            1. Stefan Schnell Post author

              Hello Tanaya,

              the SAP GUI for Windows is a 32-bit application, it can only use COM libraries which are 32-bit. If you are calling CreateObject(“ScriptX”) the SAP GUI for Windows will use automatically the correct way, you have nothing to do πŸ™‚

              Cheers

              Stefan

              (0) 
              1. tanaya amdekar

                That saved me from running behind Basis πŸ˜‰

                But still as OLE object creation is failing, so I am not able to execute Python code. Do I need to maintain OLE application via SOLE transaction?

                Because below code is running fine:

                DATA app TYPE ole2_object.

                INCLUDE OLE2INCL.

                CREATE OBJECT app ‘Excel.Application’ NO FLUSH.

                I hope you still keep patience with my little knowhow & keep helping me πŸ™‚ !!

                (0) 
                1. Stefan Schnell Post author

                  Hello Tanaya,

                  it is not necessary to customize ScriptX with the TAC SOLE. Register ScriptX as I described above. Check the function with the VBScript above. If this script works fine, the following ABAP report should also work.

                   

                  “-Begin—————————————————————–
                    Program ZSCRIPTX.

                      “-Includes———————————————————-
                        Include OLE2INCL.

                      “-Variables———————————————————
                        Data oScriptX Type OLE2_OBJECT.

                      “-Macros————————————————————
                        Define Flush.
                          Call Function ‘AC_SYSTEM_FLUSH’ Exceptions Others = 1.
                        End-Of-Definition.

                      “-Main————————————————————–
                        Create Object oScriptX ‘ScriptX’.
                        If sysubrc = 0 And oScriptXHandle > 0 And oScriptXType = ‘OLE2’.

                          Call Method Of oScriptX ‘About’.
                          Flush.

                          Free Object oScriptX.
                        EndIf.

                  “-End——————————————————————-

                  Now you should see the about box of ScriptX.

                  Let us know the result.

                  Cheers

                  Stefan

                  (0) 
  2. tanaya amdekar

    Hi Stephan,

    Now I am able to execute your above(topmost) Test program πŸ™‚ and below is the output:

    Capture.PNG

    But could not find the test.py file created. I checked the file path in debugging but there was no file in there or CMD prompt, like your shown in above screenshot πŸ˜• .

    I am not sure what went wrong with my first trial.

    Below are probable steps which might have gone wrong:

    1. I tried to open ScriptX.dll file in Notepad without unchecking ‘Always use the selected program to open this kind of file:

    Capture.PNG

    I couldn’t reset it as do not have authority to access regedit. So, I renamed with extension .DLL

    2. Commented below statement & ran rest of code to extract Python multipart archive:

    If sy-subrc = 0 And oScriptX-Handle > 0 And oScriptX-Type = ‘OLE2’.

    This might have created association error, as I got below:

    Capture.PNG

    Than I deleted all files from C:\Users\XXXXX\Documents\SAP & was able to run the program.


    3. Created 5 multipart archive, as 65,535 literals were not fitting for only 3 archives -> I don’t think this should create problem.

    With limited access on installation in my sytem, I still wish to succeed in Python code execution…

    …So please continue helping me !

    Vielen Dank…Tanaya

    (0) 
    1. Stefan Schnell Post author

      Hello Tanaya,

      it works, good to know.

      To your questions:

      1. In my example I delete the Python script file and environment. If you disable the following lines

        “-Delete Python script file———————————–
          Call Method Of oScriptX ‘DeleteFileA’
            Exporting #1 = FileName.

        “-Delete Python environment———————————–
          Call Method Of oScriptX ‘DeleteDirectory’
            Exporting #1 = ‘Python’.

        you can find both inside your SAP workdirectory.

      2. ScriptX.dll is a binary library, it is not possible to edit them with Notepad. In the FM zScriptXDll I use GUI_DOWNLOAD and EXECUTE, please check the sections “Store file” and “Register library”, whether they are working correctly in your case.
      3. Yes, it is no problem, you can create and use so much multi part archive files as you like.

      I use this kind of proceeding in very restricted Citrix environments and it works. I use only the users environment, with the registry also in the SAP context.

      You are welcome – Bitte schön πŸ™‚

      Cheers

      Stefan

      (0) 
      1. tanaya amdekar

        In step 1, I did not receive any window for input, like you showed in your screenshot:

        Capture.PNG

        So, I was looking into the SAP workdirectory. (just an info hFileMap value is 3376)

        The window should have prompted  πŸ˜• , right ?

        Also, is just 1 call method sufficient to unpack all 5 archives ?

        “-Unpack archive————————————————

                  Call Method Of oScriptX ‘Unrar’ Exporting

                    #1 = ‘Python27.part1.rar’.

                  Flush.

        (0) 
        1. Stefan Schnell Post author

          Hello Tanaya,

          yes, the window is part of the Python program and should be shown in any case. But it is not exact as in the code above, please correct the code in this case for your test.

          _ ‘print “Hello World from Python”‘.

          _ ‘input(“Press any key…”)’.

          For a better testing you could replace the complete Python script with this two lines.

          Yes, it needs only one call to unpack a multi part archive.

          Cheers

          Stefan

          (0) 
          1. tanaya amdekar

            Hi Stefan,

            Thanks for your quick replies and answers to all my silly queries.

            I had to opt for external OS command execution due to long duration of processing in background job (today got success after job ran for almost 2 hrs).

            It was pleasure interacting with you πŸ™‚ !!

            Cheers

            Tanaya

            (0) 
            1. Stefan Schnell Post author

              Hello Tanaya,

              thank you very much.

              Your questions are very good and I use your questions as indicator to clarify my help document. Also it is very good to know in which context you use my library and it is a pleasure for me to hear about your success.

              You are welcome.

              Cheers

              Stefan

              (0) 
              1. tanaya amdekar

                Hi Stefan,

                Sorry for delay!

                I could not use your library, as Python prompt window din’t appear. Also, as I needed to target mass computing, so background job was necessary. I took basis help 😳 & ran Python from SM69.

                Thanks & regards,

                Tanaya

                (0) 
                1. Stefan Schnell Post author

                  Hello Tanaya,

                  thanks for your reply. It is a pity but understandable. Your kind of proceeding, with mass computing in background processes, is not the area of application via the ABAP COM interface to a frontend server.

                  Cheers

                  Stefan

                  (0) 

Leave a Reply