• 自动将Javascipt代码翻译成Python代码
  • 支持全部ECMA Scipt 5.1
  • 可使用pyimport语法从Javascript代码中导入Python库
  • 解释速度快,可作为独立的JS解释器
  • 友好的JS执行方式,js2py.eval_js
Installation
1
$ sudo pip install js2py
Simple Example
1
2
3
4
5
6
7
8
9
10
11
>>> import js2py
>>> js2py.eval_js('console.log("Hello World!")')
'Hello World!'
>>> add = js2py.eval_js('function add(a,b){return a+b}')
>>> add
'function add(a, b) { [python code] }'
>>> add(1,2) + 3
>>> add.constructor
'function Function() { [python code] }'
>>> js2py.eval_js("Object.prototype.toString.call(Function('s', 'return s+arguments[1]')(new Date(), 7).__proto__)")
'[object String]'
More advanced usage example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# Adding Python built-in sum to the JS context:
>>> context = js2py.EvalJs({'python_sum': sum})
>>> js_code = '''
var a = 10
function f(x) {return x*x}
'''
>>> context.execute(js_code)
# Get value of variable a:
>>> context.a
10
# context.f behaves just like js function so you can supply more than 1 argument. '9'*'9' in javascript is 81.
>>> context.f('9', 0)
81
# context.f has all attributes of normal JavaScript object
>>> context.f.toString()
u'function f(x) { [python code] }'
>>> context.f.bind
function bind(thisArg) { [python code] }
# You can also add variables to the context:
>>> context.foo = [1,2,3] # context.foo is now Js Array object and behaves just like javascript array!
>>> context.foo.push(4)
4
>>> context.foo.to_list() # convert to python list
[1, 2, 3, 4]
# You can use Python objects that you put inside the context!
>>> context.eval('python_sum(new Array(1, 2, 3))')
Note
  • 忽视了”strict mode”
  • 不支持with语法
  • eval的非直接调用会被当做直接调用
Other Examples
  • In Js2Py all JavaScript objects are a subclass of PyJs object. For example JS Number is represented by PyJsNumber class. js2py.eval_js and js2py.EvalJs automatically tries to convert PyJs type to builtin python type. So for example if you execute:
    1
    >>> js2py.eval_js('var a = "hello"; a')
  • eval_js will return unicode type (u”hello”). However for complex types such conversion is impossible and JsObjectWrapper is returned. See the conversion table JsType -> PyType:
    1
    2
    3
    4
    5
    6
    >>> Boolean -> bool
    >>> String -> unicode (str in Python 3)
    >>> Number -> float (or int/long if whole number)
    >>> undefined -> None
    >>> null -> None
    >>> OTHER -> JsObjectWrapper
  • JsObjectWrapper supports: getitem, getattr, setitem, setattr, repr and call. Moreover it has to_list and to_dict methods if you want to convert it to builtin python type.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    >>> js = js2py.eval_js('d = {a:1, b:2}')
    >>> js
    {a: 1, b: 2}
    >>> type(js)
    <class 'js2py.base.JsObjectWrapper'>
    >>> js.a
    >>> 1
    >>> js['a']
    >>> 1
    >>> js.b = 20
    >>> js
    {a: 1, b: 20}
    >>> js['c'] = 30
    >>> js.to_dict()
    {u'a': 1, 'c': 30, u'b': 20}
  • Also, of course you can use Js2Py to parse (tree is the same as in esprima.js) and translate JavaScript
Parsing
1
2
>>> js2py.parse_js('var $ = 5')   
{'body': [{'kind': 'var', 'declarations': [{'init': {'raw': None, 'type': u'Literal', 'value': 5.0}, 'type': u'VariableDeclarator', 'id': {'type': u'Identifier', 'name': u'$'}}], 'type': u'VariableDeclaration'}], 'type': u'Program'}
Translating
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
>>> print js2py.translate_js('var $ = 5')
import js2py.pyjs, sys
for m in sys.modules.keys():
if m.startswith('js2py'):
del sys.modules[m]
del js2py.pyjs
del js2py
from js2py.pyjs import *
# setting scope
var = Scope( JS_BUILTINS )
set_global_object(var)
# Code follows:
var.registers([u'$'])
var.put(u'$', Js(5.0))
pyimport statement
Finally, Js2Py also supports importing any Python code from JavaScript using ‘pyimport’ statement:
>>> x = """pyimport urllib;
var result = urllib.urlopen('https://www.google.com/').read();
console.log(result.length)
"""
>>> js2py.eval_js(x)
18211