Convert your Python to JavaScript with Pyjamas
Posted in JavaScript, Python on 11/13/2009 11:12 pm by JennyThe problem
I faced an irritating situation last year in a project I was working on. I was creating a screen that pulled in a very large set of data from the database then did various calculations on the data based on input in a form. The results were shown in several grids and a flash chart all on the same page. These exact same calculations also needed to be run to generate a PDF on the server. I didn’t want to go back to the server for the calculation because the amount of data that needed to go back and forth was very large. At the same time, I didn’t want to write and maintain a piece of code that involved 30+ math operations in both JavaScript and Python.
So I discovered Pyjamas!
A little background: the Pyjamas project was started to be the Python answer to GWT. It’s a framework that allows you to define an entire UI in Python which is then converted to JavaScript and HTML. What I found though was that it’s possible to use the Python to JavaScript converter in the project to compile your own Python to JavaScript even if you don’t need the UI framework Pyjamas provides. This was a perfect solution to my problem!
Unfortunately, Pyjamas was still in its infancy at that time, so I had to use a much stripped down subset of Python to get it to build JavaScript successfully. Once I figured out the tricks, it was a great way to avoid a painful round trip to the server and yet also avoid maintaining the same logic in two languages.
Fast forward to today. The Pyjamas project has a greatly improved Python to JavaScript compiler. You can now import multiple modules through the usual Python import functionality. The painful things I had to do before (like not use the dict constructor!) are no longer necessary. There’s even a way to include external JavaScript files from Python for use in your final generated script.
How do I use this?
It looks like at this very moment (mid-November 2009) the compiler inside of Pyjamas is in the process of being broken out into a module called pyjampiler that makes it a little easier to use it independently of the larger project. This is currently getting moved into the main code, so look for it inside of the next release. For now you can download it from the link above. Playing around with pyjampiler is this easy:
pyjampiler.py --output=my_javascript.js --entry=my_python
Really! Your python imports will be followed, converted, and linked together. You’ll get JavaScript that behaves like your Python.
Tips for success
As cool as this is, there are some limits. You can’t import whatever you like from the Python standard library. The JavaScript generated is going to be much more verbose than something you would have written yourself. You’ll need to include a helper .js file which is not one of the frameworks you’re already using (supposedly it’ll play nice).
I think this technique is best limited to functionality like I described in the beginning of this post. I implemented my logic as a function that took in two dicts and returned another dict of results. The only thing handled by the piece that was converted was the arithmetic required to drive the calculator. I wrote JavaScript to handle the DOM manipulations required to display the results on the client and Python to turn the results into a PDF on the server.
What do you think? Is this a reasonable way to avoid maintaining the same logic in two places? Have a better solution?