Revisiting Python and SAP (With PyRFC)
A couple of days back Srdjan Boskovic wrote a blog called Python / ABAP Stack. This for sure, bring me back memories as I already played a lot with sapnwrfc from Piers Harding
After downloading the sapnwrfc2 package from the PyRFC project’s website and some email exchanges with Srdjan and Jonas Kunze I was able to set up and start working with it.
(Actually, the problem were not related to installing the connector itself, which was really easy, but more related to the nwrfcsdk as I have the 64bit version on my Windows 7 laptop and I needed the 32 bits for the connector…in the end, I used my VMWare Windows XP to get rid of any possible conflicts).
You may ask…why another Python to SAP connector? Simply, while Pier’s one is awesome, it lacked some features that SAP needed for internal development, so this guys take the hard work of making from the scratch exactly what they needed…one of the beauties of being a developer…you can grab an idea…a turn it into a full blown application or RFC connector in this case…
As a way to introduce PyRFC, the best example is always showing something with the flights tables…which are always present in every ERP installation and as I have it used before on SAP HANA and Python? Yes Sir!, Bottle seemed to be a good option…because you don’t want to see more command line screen, don’t you?
I will show the code first and the I will tell you about some of the most significant changes that I can see from using PyRFC (And by the way…I fight myself to make my example better and have some error handling, which is always good, even for humble blogs like this one).
Bottle_PyRFC.py |
---|
from bottle import get, post, request, run, redirect from sapnwrfc2 import Connection, ABAPApplicationError, LogonError from ConfigParser import ConfigParser conn = “” @get(‘/login’) def login_form(): return ”'<DIV ALIGN=’CENTER’><BR><BR><BR><BR> <H1>Python (Bottle) & SAP – using PyRFC</H1> <BR><TABLE BORDER=’1′ BORDERCOLOR=’BLUE’ BGCOLOR=’WHITE’> <FORM METHOD=’POST’> <TR><TD>User</TD><TD> <INPUT TYPE=’TEXT’ NAME=’User’></TD></TR> <TR><TD>Password</TD> <TD><INPUT TYPE=’PASSWORD’ NAME=’Passwd’></TD></TR> <TR><TD COLSPAN=’2′ ALIGN=’CENTER’> <INPUT TYPE=’SUBMIT’ value=’Log In’ NAME=’LOG_IN’> <INPUT TYPE=’RESET’ value=’Clear’></TD></TR> </FORM> <TABLE> </DIV>”’ @post(‘/login’) def login_submit(): global conn try: user = request.forms.get(‘User’) passwd = request.forms.get(‘Passwd’) config = ConfigParser() config.read(‘sapnwrfc.cfg’) params_connection = config._sections[‘connection’] params_connection[“user”] = user params_connection[“passwd”] = passwd conn = Connection(**params_connection) redirect(“/choose”) except LogonError: redirect(“/error”) @get(‘/choose’) def choose_table(): return ”'<CENTER> <FORM METHOD=’POST’> <INPUT TYPE=’TEXT’ NAME=’Table’><BR> <INPUT TYPE=’SUBMIT’ value=’Show Table’ NAME=’Show_Table’> </FORM> </CENTER>”’ @get(‘/error’) def error(): output = “<div align=’center’><h1>Invalid username or password</h1></div>” return output @post(‘/choose’) def show_table(): global conn fields = [] fields_name = [] counter = 0 table = request.forms.get(‘Table’) try: tables = conn.call(“RFC_READ_TABLE”, QUERY_TABLE=table, DELIMITER=’|’) data_fields = tables[“DATA”] data_names = tables[“FIELDS”] long_fields = len(data_fields) long_names = len(data_names) for line in range(0, long_fields): fields.append(data_fields[line][“WA”].strip()) for line in range(0, long_names): fields_name.append(data_names[line][“FIELDNAME”].strip()) output = “<div align=’center’><h1>%s</h1></center>” % table output += “<table border=’1′><tr>” for line in range(0, long_names): field_name = fields_name[line] output += “<th bgcolor=’#B8D5F5′> %s </th>” % field_name output += “</tr>” for line in range(0, long_fields): counter += 1 if(counter % 2 == 0): output += “<tr bgcolor=’#DCE1E5′>” else: output += “<tr>” data_split = fields[line].split(“|”) for line in range(0, long_names): output += “<td> %s </td>” % data_split[line] output += “</tr>” output += “</table>” except ABAPApplicationError: output = “<div align=’center’><h1>Table %s was not found</h1></div>” % table return output return output conn.close() run(host=’localhost’, port=8080) |
So, for me PyRFC has some mayor benefits, like the option to catch ABAPApplicationError and LoginError (I assume that Pier’s version have it as well, but I never worried to look for it…shame on me), also the way to call the Function Module is very clean, a simple Python function that will receive as parameters the FM name and the parameters, taking from us the need to define each parameter as an attribute of the object. Also, it’s really fast and it can be used on the Server side…but we will talk about that later…in other blog…when I got the chance to actually work with it…
Let’s run this program and see how it looks…when running it from Python you might need to go to your browser a pass the following link (as we’re executing a Bottle application):
As always, was very enjoyable to work with Python, and of course, when mixing it my PyRFC the fun exceed my expectations as right now it’s almost 8:00 pm on Saturday night…and I’m posting a blog of what I worked on almost all afternoon…programming is fun…don’t forget it…
I have been wanting to learn more Python for some years, but haven't seen a use for it at work. While reading your other Py blogs and this I just realized how this could help.
About 1 every couple of months we need data from several tables - different tables for auditors and budget people - that our Z reports don't provide. SQVI lacks the ability to just got the results, and I really don't want to work with Excel or Access. I usually end up dumping the data in several files, import them into DEV and write a quick throw way ALV to get the results.
Using Python might be easier!
Anyway - Blag thanks for the great posts!! I enjoy them even if I don't use it.
Steve:
Totally agree...Python is just totally awesome...I remember that I start learning it just because Piers released his RFC connector...
With PyRFC I just confirm that Python is a totally needed tool that can really stand up to any job...
I hope you find a way to use it in your projects and I hope that you can blog about it 😉
Greetings,
Blag.
For the record PyRFC is available on github at: SAP/PyRFC · GitHub
The project is called PyRFC there, not sapnwrfc2.
One more thing: Piers' sapnwrfc only depends on PyYAML. PyRFC pulls in: cython==0.20.1, setuptools-git, Jinja2, markupsafe, Pygments, docutils, Sphinx