lunes, 19 de noviembre de 2012

Calling Python from ERP (With PyRFC)


If you read my previous blog Revisiting Python and SAP (With PyRFC) then you will recall that I said that with PyRFC we can not only retrieve data or execute services from the ERP side, but also use PyRFC as a server to be called from the ERP.

In other words, we can create a function in Python that will hosted by PyRFC and then called by an ERP function module.

In this blog we're going to build and XML comparator, that will read two XML files and will return the additions and deletions.

You might have already PyRFC installed, so let's go to the steps we need to follow to make this work...

First, we need to get the information of the Gateway server, so let's go to transaction SMGW and choose Goto --> Parameters --> Display. At the end of the table, you will find the needed information.


Then, we need to create an TCP/IP connection, so we can call our PyRFC Server. Go to SM59 and create the following.


Now, we need to create a file that will contain our connection information, for both the ERP and the Gateway Server.



In my testing, I used the gwhost that comes from the SMGW but somehow it didn't work properly...I used the value of ashost...so try with one first and if it doesn't work, do it like me.

Now, log into your ERP and create a simple structure called ZXML_RESPONSE.


Create a Table Type using this structure and call it ZXML_RESPONSE_TT.

Now, go to transaction SE37 and create a function module called ZXML_DIFF. This FM will be empty as the work will be done on the Python side.


For now...we're done with the ERP side...let's move to the Python side...

We need two libraries to make this work ListComparator and ElementTree, you can install both using easy_install.

The code is simple, Python will receive two path's, one for each XML, read it's contents, compare the differences and return what has been added and what has been deleted.



PyRFC_XML_Diff.py
from sapnwrfc2 import Server, Connection
from ConfigParser import ConfigParser
from elementtree import ElementTree as ET
from listcomparator.comparator import Comparator

config = ConfigParser()
config.read('sapnwrfc.cfg')


def xml_diff(request_context, XML_1="", XML_2="", ROOT="",
                    ADDITIONS=[], DELETIONS=[]):
    add_list = {}
    del_list = {}
    length = 0
    lower_root = ROOT.encode('utf-8')
    root_old = ET.parse(XML_1).getroot()
    root_new = ET.parse(XML_2).getroot()
    objects_old = root_old.findall(lower_root.lower())
    objects_new = root_new.findall(lower_root.lower())
    objects_old = [ET.tostring(o) for o in objects_old]
    objects_new = [ET.tostring(o) for o in objects_new]
    my_comp = Comparator(objects_old, objects_new)
    my_comp.check()

    for e in my_comp.additions:
        line = e.split("\n")
        length = len(line)
        for i in range(0, length):
            add_list = {}
            add_list.update({"LINE": line[i]})
            ADDITIONS.append(add_list)

    for e in my_comp.deletions:
        line = e.split("\n")
        length = len(line)
        for i in range(0, length):
            del_list = {}
            del_list.update({"LINE": line[i]})
            DELETIONS.append(del_list)

    return {
        'ADDITIONS': ADDITIONS,
        'DELETIONS': DELETIONS
    }

params_connection = config._sections['connection']
conn = Connection(**params_connection)
func_xml_diff = conn.get_function_description("ZXML_DIFF")

params_gateway = config._sections['gateway']
server = Server(**params_gateway)
server.install_function(func_xml_diff, xml_diff)
print "--- Server registration and serving ---"
server.serve(100)

Now that we have out Python Server ready...let's define a couple of XML to test this.




We can clearly see that both XML files are different...and that Blag individual has received a suspicious raise in his quantity...let's analyse this...

Go back to transaction SE37 and run the function. It's very important to fill the RFC Target sys parameter with the name we used to named our RFC destination.


The ROOT parameter will tell our function which one is the parent function of the XML files.

Now, run the PyRFC_XML_Diff.py application and you will see this, that will indicate us that the server is up and running.



Now, run the function and we will get our response from Python.


Now, we can analyse both the ADDITIONS and DELETIONS tables...


We can see that something happened with the account number 0001, which wasn't added, but it's value was modified. Also, in the second XML, Kiara's account was added.


So now, everything fall in line...the account for Blag used to have a quantity of 100 and now it has a quantity of 10,000.

So as you can see, we only use an empty shell from ERP to call all the functionality from Python.

Greetings,

Blag.

4 comentarios:

Unknown dijo...

Dear sir, I'd like to download PyRfc from http://scn.sap.com/community/code-exchange but it says it is closed. How can I access that python module? Or should I usehttps://pypi.python.org/pypi/sapnwrfc/ instead?

TIA

Alvaro "Blag" Tejada Galindo dijo...

Çağatay:

PyRFC and Python/sapnwrfc work in a different way, the first one allows you to either call ERP from Python or call Python from ERP...the second only allows you to connect to ERP and fetch/put data...

I will reply to the email you send to the SAP Developer Center -:)

Greetings,

Blag.

vindolin dijo...

Hello Alvaro,

I tried to download the PyRFC connector but apparently the SAP code exchange is now closed.

Is there a new location where I can get my hands on it?

Greetings,
Thomas


Alvaro "Blag" Tejada Galindo dijo...

Dear Thomas:

I have contacted the author and he's waiting for an Outbound Open Source Approval to be able to publish it on sap.github.io so please be patient...it will be there -;)

Greetings,

Blag.
Developer Experience.