py2php
py2php is a utility that will auto-translate python code into PHP code.
It is intended as a porting aid only. You will still need to review the generated PHP and make tweaks. But it does handle a lot of the grunt work and common cases.
py2php is a heavily modified copy of pyjs.py from the pyjamas project. pyjs.py was written to translate python to javascript. py2php changes the output semantics from JS to php.
Example
Here's a simple python program to generate a sequence of fibonacci numbers.
def gen_fib(count):
i = 1
if count == 0:
fib = []
elif count == 1:
fib = [1]
elif count == 2:
fib = [1,1]
elif count > 2:
fib = [1,1]
while i < (count - 1):
fib.append(fib[i] + fib[i-1])
i += 1
return fib
print gen_fib(10)
and here is the autogenerated PHP.
<?php
require_once('py2phplib.php');
function gen_fib($count) {
$i = 1;
if (($count == 0)) {
$fib = array();
}
else if (($count == 1)) {
$fib = array(1);
}
else if (($count == 2)) {
$fib = array(1, 1);
}
else if (($count > 2)) {
$fib = array(1, 1);
while (($i < ($count - 1))) {
$fib[] = ($fib[$i] + $fib[($i - 1)]);
$i += 1;
}
}
return $fib;
}
pyjslib_printFunc(gen_fib(10));
Both produce the exact same output:
$ python fibonacci.py
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
$ php fibonacci.py.php
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
The file py2phplib.php contains some PHP functions that emulate python keywords such as print, range, etc. py2php automatically renames these keywords to call the emulated functions instead.
Look in the tests directory for more examples.
translate_python_to_php
translate_python_to_php is a wrapper script for py2php. Run it in any directory without arguments and it will attempt to translate all the .py files into .php files.
Run it with one or more arguments, and it will attempt to translate the files in the argument list.
String Concatenation
Python uses + for string concatenation and PHP uses dot (.).
Because python variables are dynamically typed, it is not possible for py2php to know if a given variable represents a string or a number.
py2php attempts to deal with this by:
-
If either side of the expression is a string constant, then use dot operator.
-
If either side of the expression is a variable that contains "str" or "buf" in the name, then use dot operator.
-
For all other cases, use plus operator.
This means that if your string variable names do not contain "str" or "buf" then you will need to manually change all related occurrences of "+" to ".".
Porting Convention
When porting python code, I have been manually creating a subdirectory named _autotranslated, into which I move all the original .py files. I then run translate_python_to_php which creates all the translated .php files. I then copy (not move!) those generated files back into the parent directory for review and tweaking, to finish the port.
This way, the _autotranslated directory contains only original .py files and the autogenerated .php files. This should make things easier in the future when the upstream python project releases a new version. Then we will simply copy the new .py files into a new tmp directory, re-run the autotranslater, and then we have a nice PHP <--> PHP diff we can use as a porting aid. Once the port is complete, the tmp directory files should replace the contents of _autotranslated directory.