Hello community,

I presented until now in the series “How to use actual SAPNetWeaver RFC Library with Pyhton” :

Here now an example how to define and run ABAP code from Python.

All constants, structures and prototypes are in the quasi-include file sapnwrfc.py.

The ABAP report itself is an array of strings. We use the function module (FM) RFC_ABAP_INSTALL_AND_RUN to implement and execute the ABAP program. We set the report line by line in the PROGRAM table of the FM, invoke the function and get a result back in the WRITES table. We read each line of ZEILE and add it to a Result string.

# -*- coding: iso-8859-15 -*-
#-Begin-----------------------------------------------------------------

#-Include---------------------------------------------------------------
FileName = "sapnwrfc.py"
exec(compile(open(FileName).read(), FileName, "exec"))

#-Main------------------------------------------------------------------

#-Connection parameters-------------------------------------------------
RfcConnParams[0].name = "ASHOST"; RfcConnParams[0].value = "NSP"
RfcConnParams[1].name = "SYSNR" ; RfcConnParams[1].value = "00"
RfcConnParams[2].name = "CLIENT"; RfcConnParams[2].value = "001"
RfcConnParams[3].name = "USER"  ; RfcConnParams[3].value = "BCUSER"
RfcConnParams[4].name = "PASSWD"; RfcConnParams[4].value = "minisap"

#-ABAPReport------------------------------------------------------------
#-
#- Code your ABAP report here. The length of each line must be equal or
#- less than 72 characters.
#-
#-----------------------------------------------------------------------
ABAP=[]
ABAP.append("Report zTest Line-Size 256.")
ABAP.append("Write: 'Hello World from'.")
ABAP.append("Write: sy-sysid.")

hRFC = SAP.RfcOpenConnection(RfcConnParams, 5, RfcErrInf)
if hRFC != None:

  charBuffer = create_unicode_buffer(256 + 1)
  Result = ""

  hFuncDesc = SAP.RfcGetFunctionDesc(hRFC, "RFC_ABAP_INSTALL_AND_RUN", \
    RfcErrInf)

  if hFuncDesc != 0:
    hFunc = SAP.RfcCreateFunction(hFuncDesc, RfcErrInf)
    if hFunc != 0:

      hTable = c_void_p(0)

      #-Writes the report into the PROGRAM table------------------------
      if SAP.RfcGetTable(hFunc, "PROGRAM", hTable, RfcErrInf) == RFC_OK:
        for i in range(0, len(ABAP)):
          hRow = SAP.RfcAppendNewRow(hTable, RfcErrInf)
          rc = SAP.RfcSetChars(hRow, "LINE", ABAP[i], len(ABAP[i]), \
            RfcErrInf)

        if SAP.RfcInvoke(hRFC, hFunc, RfcErrInf) == RFC_OK:
          #-Gets the result from the WRITES table-----------------------
          if SAP.RfcGetTable(hFunc, "WRITES", hTable, RfcErrInf) == RFC_OK:
            RowCount = c_ulong(0)
            rc = SAP.RfcGetRowCount(hTable, RowCount, RfcErrInf)
            rc = SAP.RfcMoveToFirstRow(hTable, RfcErrInf)
            for i in range(0, RowCount.value):
              hRow = SAP.RfcGetCurrentRow(hTable, RfcErrInf)
              rc = SAP.RfcGetChars(hRow, "ZEILE", charBuffer, 256, \
                RfcErrInf)
              Result = Result + charBuffer.value
              if i < RowCount.value:
                rc = SAP.RfcMoveToNextRow(hTable, RfcErrInf)

            #-Shows the result------------------------------------------
            print(Result)

      rc = SAP.RfcDestroyFunction(hFunc, RfcErrInf)

  rc = SAP.RfcCloseConnection(hRFC, RfcErrInf)

else:
  print(RfcErrInf.key)
  print(RfcErrInf.message)

del SAP

#-End-------------------------------------------------------------------

As you can see, it is no problem to define and execute an ABAP program inside Python.

2015/09/16: Three days ago the new Python release 3.5.0 has been published. The method above works perfect with the new release.

2017/04/24: I check the method above with Python release 3.6.1 x64 and with the SAP NetWeaver RFC library 721 PL42 x64 and it works perfect.

Hint: In actual releases of SAP AS you need an extra authorization object S_RFCRAIAR to execute reports via RFC_ABAP_INSTALL_AND_RUN.

Enjoy it.

Cheers
Stefan

 

To report this post you need to login first.

10 Comments

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

  1. RAMESH BABU A

    Hi Stefan,

    Thank you for this post. I have referred this and implemented successfully in my assignment. Here we are writing the ABAP code and passing via python script, is it possible to call an existing ABAP program using Python scripts. If it is possible, then kindly guide me to proceed further.

    Regards

    Ramesh

    (0) 
    1. Stefan Schnell Post author

      Hello Ramesh,

      thanks for your reply.

      As far as I know it is not possible to execute an ABAP program via RFC directly. You must code a wrapper RFC enabled function module on your SAP system which calls your ABAP program via SUBMIT. On this little detour you can reach the same result.

      This could be a possible solution where the output of the program is set to an export parameter from the function module of the type string:

      Function Z_TEST.

      *”———————————————————————-

      *”*”Local Interface:

      *”  EXPORTING

      *”     VALUE(E_RESULT) TYPE  STRING

      *”———————————————————————-

        Data lv_oList Type Standard Table Of ABAPLIST.

        Data lv_aList Type Standard Table Of LISTZEILE.

        Data lv_Zeile Type LISTZEILE.

        Submit ZTEST2 And Return Exporting List To Memory.

        Call Function ‘LIST_FROM_MEMORY’

          Tables

            LISTOBJECT = lv_oList

          Exceptions

           Others = 1.

        Call Function ‘LIST_TO_ASCI’

         Tables

           LISTASCI = lv_aList

           LISTOBJECT = lv_oList

         Exceptions

           Others = 1.

        Loop At lv_aList Into lv_Zeile.

          Concatenate e_Result lv_Zeile CL_ABAP_CHAR_UTILITIES=>CR_LF

            Into e_Result.

        EndLoop.

      EndFunction.

      Here the report:

      REPORT  ZTEST2.

        Write: / ‘Hello World’.

      And now you can invoke this function module via Python as I described here.

      Best regards.

      Stefan

      (0) 
  2. RAMESH BABU A

    Hi Stefan,

    I have another query, the ABAP report which i am passing via Python script is working in one SAP Module(CRM), but the same code is not working in another module(BI or BS) and failing with the auths error. When i checked with auths team, they replied that my program is creating $TMP package which will not be permitted.

    Could you please recommend the way forward.

    Regards

    Ramesh.

    (0) 
    1. Stefan Schnell Post author

      Hello Ramesh,

      your (RFC) user needs the following authorization objects

      • S_ADMI_FCD = System Authorizations
        Field  S_ADMI_FCD, Value  RFCA
      • S_RFCRAIAR = Auth. object for RFC_ABAP_INSTALL_AND_RUN function module
        Field  RFC_RAIAR, Value 16
      • S_TCODE = Transaction Code Check at Transaction Start
        Field TCD, Value SE38
      • S_DEVELOP = ABAP Workbench
        Field DEVCLASS, Value $TMP
        Field OBJTYPE, Value PROG
        Field  OBJNAME, Value Z$$$XRFC
        Field P_GROUP
        Field ACTVT, Value 1 and 2

      And of course S_RFC 😉

      Also your target SAP system needs different status – look in table TADIR, PGMID Head OBJECT Syst EDTFLAG (Object can only be edited with a special editor) must be space and table T000, field CCNOCLIIND (Maintenance authorization for objects in all clients) must be space or 1.

      Look also the discussion here.

      Best regards

      Stefan

      (0) 
      1. RAMESH BABU A

        Hi Stefan,

        I have requested the Auths team to assign the suggested roles, but they reverted that access cannot be granted as per the policy. Instead they recommended to try the other solution advised by you by developing the ABAP code & FM in SAP box and then to call the same via python scripts.

        Once after creating the FM, i will get back to you.

        Thank you for the time.

        Regards

        Ramesh.

        (0) 
      2. RAMESH BABU A

        Hello Stefan,

        Hope you are doing good!

        I have another request, I understood the above recommendation. Now I want to pass a value to ABAP report program as parameter for the data selection from Python GUI. Could you please suggest a way to do this.


        Regards

        Ramesh

        (0) 
        1. Stefan Schnell Post author

          Hello Ramesh,

          thanks for your reply, I am well, hope you too.

          Here my report example:

          "-Begin--------------------------------------------------
          Report YTEST2.
          
            Parameters p_Name Type String.
          
            Write: / `Hello ` && p_Name.
          
          "-End----------------------------------------------------
          

          /wp-content/uploads/2016/03/001_908514.jpg

          Here the RFC-enabled function module to call this report:

          FUNCTION Y_TEST2.
          *"-------------------------------------------------------
          *"*"Local interface:
          *"  IMPORTING
          *"     VALUE(I_NAME) TYPE  STRING DEFAULT 'STEFAN'
          *"  EXPORTING
          *"     VALUE(E_RESULT) TYPE  STRING
          *"-------------------------------------------------------
          
            Data lv_oList Type Standard Table Of ABAPLIST.
            Data lv_aList Type Standard Table Of LISTZEILE.
            Data lv_Zeile Type LISTZEILE.
          
            Submit YTEST2
              With p_Name EQ i_name
              And Return Exporting List To Memory.   Call Function 'LIST_FROM_MEMORY'     Tables       LISTOBJECT = lv_oList     Exceptions      Others = 1.   Call Function 'LIST_TO_ASCI'    Tables      LISTASCI = lv_aList      LISTOBJECT = lv_oList    Exceptions      Others = 1.   Loop At lv_aList Into lv_Zeile.     Concatenate e_Result lv_Zeile CL_ABAP_CHAR_UTILITIES=>CR_LF       Into e_Result.   EndLoop. EndFunction.

          As you can see I add only a With, and get the expected result.

          /wp-content/uploads/2016/03/002_908528.jpg

          Now you can call the function module as in the example above via

          • RfcGetFunctionDesc
          • RfcCreateFunction
          • RfcSetChars(hFunc, “I_NAME”, “Ramesh”, 6, RfcErrInf)
          • RfcInvoke
          • RfcGetChars(hFunc, “E_RESULT”, charBuffer, 1024, RfcErrInf)

          Let us know your results.

          Cheers

          Stefan

          (0) 
  3. Stefan Schnell Post author

    Hello Ramesh,

    here the main Python code:

    Result = create_unicode_buffer(256 + 1)
    hRFC = SAP.RfcOpenConnection(RfcConnParams, 5, RfcErrInf)
    if hRFC != None:
      hFuncDesc = SAP.RfcGetFunctionDesc(hRFC, "Y_TEST2", RfcErrInf)
      if hFuncDesc != 0:
        hFunc = SAP.RfcCreateFunction(hFuncDesc, RfcErrInf)
        if hFunc != 0:
          rc = SAP.RfcSetChars(hFunc, "I_NAME", "Stefan", 6, RfcErrInf)
          if SAP.RfcInvoke(hRFC, hFunc, RfcErrInf) == RFC_OK:
            rc = SAP.RfcGetChars(hFunc, "E_RESULT", Result, 256, RfcErrInf)
            print("Invoke successful")
            print(Result.value)
          else:
            print("Invoke not successful")
          rc = SAP.RfcDestroyFunction(hFunc, RfcErrInf)
      rc = SAP.RfcCloseConnection(hRFC, RfcErrInf)
    else:
      print(RfcErrInf.key)
      print(RfcErrInf.message)
    del SAP
    

    Your report is okay, but please change the parameter line to

    PARAMETERS p_name TYPE string LOWER CASE.

    to differentiate between upper and lower case.

    In my case it delivers:

    Invoke successful
    23.03.2016                          Report YTEST2                                  1
    
    ------------------------------------------------------------------------------------
    
           43        171
    

    Let us know your results.

    Cheers

    Stefan

    (0) 

Leave a Reply