Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
stefan_schnell
Active Contributor


I presented until now in the series "How to use 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.


Here the include file:
#-Begin-----------------------------------------------------------------

#-Packages--------------------------------------------------------------
from ctypes import *
import platform, os


#-Structures------------------------------------------------------------
class RFC_ERROR_INFO(Structure):
_fields_ = [("code", c_long),
("group", c_long),
("key", c_wchar * 128),
("message", c_wchar * 512),
("abapMsgClass", c_wchar * 21),
("abapMsgType", c_wchar * 2),
("abapMsgNumber", c_wchar * 4),
("abapMsgV1", c_wchar * 51),
("abapMsgV2", c_wchar * 51),
("abapMsgV3", c_wchar * 51),
("abapMsgV4", c_wchar * 51)]

class RFC_CONNECTION_PARAMETER(Structure):
_fields_ = [("name", c_wchar_p),
("value", c_wchar_p)]


#-Constants-------------------------------------------------------------

#-RFC_RC - RFC return codes---------------------------------------------
RFC_OK = 0
RFC_COMMUNICATION_FAILURE = 1
RFC_LOGON_FAILURE = 2
RFC_ABAP_RUNTIME_FAILURE = 3
RFC_ABAP_MESSAGE = 4
RFC_ABAP_EXCEPTION = 5
RFC_CLOSED = 6
RFC_CANCELED = 7
RFC_TIMEOUT = 8
RFC_MEMORY_INSUFFICIENT = 9
RFC_VERSION_MISMATCH = 10
RFC_INVALID_PROTOCOL = 11
RFC_SERIALIZATION_FAILURE = 12
RFC_INVALID_HANDLE = 13
RFC_RETRY = 14
RFC_EXTERNAL_FAILURE = 15
RFC_EXECUTED = 16
RFC_NOT_FOUND = 17
RFC_NOT_SUPPORTED = 18
RFC_ILLEGAL_STATE = 19
RFC_INVALID_PARAMETER = 20
RFC_CODEPAGE_CONVERSION_FAILURE = 21
RFC_CONVERSION_FAILURE = 22
RFC_BUFFER_TOO_SMALL = 23
RFC_TABLE_MOVE_BOF = 24
RFC_TABLE_MOVE_EOF = 25
RFC_START_SAPGUI_FAILURE = 26
RFC_ABAP_CLASS_EXCEPTION = 27
RFC_UNKNOWN_ERROR = 28
RFC_AUTHORIZATION_FAILURE = 29

#-RFCTYPE - RFC data types----------------------------------------------
RFCTYPE_CHAR = 0
RFCTYPE_DATE = 1
RFCTYPE_BCD = 2
RFCTYPE_TIME = 3
RFCTYPE_BYTE = 4
RFCTYPE_TABLE = 5
RFCTYPE_NUM = 6
RFCTYPE_FLOAT = 7
RFCTYPE_INT = 8
RFCTYPE_INT2 = 9
RFCTYPE_INT1 = 10
RFCTYPE_NULL = 14
RFCTYPE_ABAPOBJECT = 16
RFCTYPE_STRUCTURE = 17
RFCTYPE_DECF16 = 23
RFCTYPE_DECF34 = 24
RFCTYPE_XMLDATA = 28
RFCTYPE_STRING = 29
RFCTYPE_XSTRING = 30
RFCTYPE_BOX = 31
RFCTYPE_GENERIC_BOX = 32

#-RFC_UNIT_STATE - Processing status of a background unit---------------
RFC_UNIT_NOT_FOUND = 0
RFC_UNIT_IN_PROCESS = 1
RFC_UNIT_COMMITTED = 2
RFC_UNIT_ROLLED_BACK = 3
RFC_UNIT_CONFIRMED = 4

#-RFC_CALL_TYPE - Type of an incoming function call---------------------
RFC_SYNCHRONOUS = 0
RFC_TRANSACTIONAL = 1
RFC_QUEUED = 2
RFC_BACKGROUND_UNIT = 3

#-RFC_DIRECTION - Direction of a function module parameter--------------
RFC_IMPORT = 1
RFC_EXPORT = 2
RFC_CHANGING = RFC_IMPORT + RFC_EXPORT
RFC_TABLES = 4 + RFC_CHANGING

#-RFC_CLASS_ATTRIBUTE_TYPE - Type of an ABAP object attribute-----------
RFC_CLASS_ATTRIBUTE_INSTANCE = 0
RFC_CLASS_ATTRIBUTE_CLASS = 1
RFC_CLASS_ATTRIBUTE_CONSTANT = 2

#-RFC_METADATA_OBJ_TYPE - Ingroup repository----------------------------
RFC_METADATA_FUNCTION = 0
RFC_METADATA_TYPE = 1
RFC_METADATA_CLASS = 2


#-Variables-------------------------------------------------------------
ErrInf = RFC_ERROR_INFO; RfcErrInf = ErrInf()
ConnParams = RFC_CONNECTION_PARAMETER * 5; RfcConnParams = ConnParams()
SConParams = RFC_CONNECTION_PARAMETER * 3; RfcSConParams = SConParams()


#-Library---------------------------------------------------------------
if str(platform.architecture()[0]) == "32bit":
os.environ['PATH'] += ";C:\\SAPRFCSDK\\32bit"
SAPNWRFC = "C:\\SAPRFCSDK\\32bit\\sapnwrfc.dll"
elif str(platform.architecture()[0]) == "64bit":
os.environ['PATH'] += ";C:\\SAPRFCSDK\\64bit"
SAPNWRFC = "C:\\SAPRFCSDK\\64bit\\sapnwrfc.dll"

SAP = windll.LoadLibrary(SAPNWRFC)

#-Prototypes------------------------------------------------------------
SAP.RfcAppendNewRow.argtypes = [c_void_p, POINTER(ErrInf)]
SAP.RfcAppendNewRow.restype = c_void_p

SAP.RfcCloseConnection.argtypes = [c_void_p, POINTER(ErrInf)]
SAP.RfcCloseConnection.restype = c_ulong

SAP.RfcCreateFunction.argtypes = [c_void_p, POINTER(ErrInf)]
SAP.RfcCreateFunction.restype = c_void_p

SAP.RfcCreateFunctionDesc.argtypes = [c_wchar_p, POINTER(ErrInf)]
SAP.RfcCreateFunctionDesc.restype = c_void_p

SAP.RfcDestroyFunction.argtypes = [c_void_p, POINTER(ErrInf)]
SAP.RfcDestroyFunction.restype = c_ulong

SAP.RfcDestroyFunctionDesc.argtypes = [c_void_p, POINTER(ErrInf)]
SAP.RfcDestroyFunctionDesc.restype = c_ulong

SAP.RfcGetChars.argtypes = [c_void_p, c_wchar_p, c_void_p, c_ulong, \
POINTER(ErrInf)]
SAP.RfcGetChars.restype = c_ulong

SAP.RfcGetCurrentRow.argtypes = [c_void_p, POINTER(ErrInf)]
SAP.RfcGetCurrentRow.restype = c_void_p

SAP.RfcGetFunctionDesc.argtypes = [c_void_p, c_wchar_p, POINTER(ErrInf)]
SAP.RfcGetFunctionDesc.restype = c_void_p

SAP.RfcGetRowCount.argtypes = [c_void_p, POINTER(c_ulong), \
POINTER(ErrInf)]
SAP.RfcGetRowCount.restype = c_ulong

SAP.RfcGetStructure.argtypes = [c_void_p, c_wchar_p, \
POINTER(c_void_p), POINTER(ErrInf)]
SAP.RfcGetStructure.restype = c_ulong

SAP.RfcGetTable.argtypes = [c_void_p, c_wchar_p, POINTER(c_void_p), \
POINTER(ErrInf)]
SAP.RfcGetTable.restype = c_ulong

SAP.RfcGetVersion.argtypes = [POINTER(c_ulong), POINTER(c_ulong), \
POINTER(c_ulong)]
SAP.RfcGetVersion.restype = c_wchar_p

SAP.RfcInstallServerFunction.argtypes = [c_wchar_p, c_void_p, \
c_void_p, POINTER(ErrInf)]
SAP.RfcInstallServerFunction.restype = c_ulong

SAP.RfcInvoke.argtypes = [c_void_p, c_void_p, POINTER(ErrInf)]
SAP.RfcInvoke.restype = c_ulong

SAP.RfcListenAndDispatch.argtypes = [c_void_p, c_ulong, POINTER(ErrInf)]
SAP.RfcListenAndDispatch.restype = c_ulong

SAP.RfcMoveToFirstRow.argtypes = [c_void_p, POINTER(ErrInf)]
SAP.RfcMoveToFirstRow.restype = c_ulong

SAP.RfcMoveToNextRow.argtypes = [c_void_p, POINTER(ErrInf)]
SAP.RfcMoveToNextRow.restype = c_ulong

SAP.RfcOpenConnection.argtypes = [POINTER(ConnParams), c_ulong, \
POINTER(ErrInf)]
SAP.RfcOpenConnection.restype = c_void_p

SAP.RfcPing.argtypes = [c_void_p, POINTER(ErrInf)]
SAP.RfcPing.restype = c_ulong

SAP.RfcRegisterServer.argtypes = [POINTER(SConParams), c_ulong, \
POINTER(ErrInf)]
SAP.RfcRegisterServer.restype = c_void_p

SAP.RfcSetChars.argtypes = [c_void_p, c_wchar_p, c_wchar_p, c_ulong, \
POINTER(ErrInf)]
SAP.RfcSetChars.restype = c_ulong

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



Enjoy it.

13 Comments