在上一篇測試中使用 Pyexecjs 在 Python 中執行 Javascript 程式碼後, 接著要來測試第二個套件 js2py, 由於篇幅太長所以放到本篇. 本系列前一篇文章參考 :
js2py 套件為 PiotrDabkowski 以純 Python 開發的 Javascript 轉譯器, 此套件完整支援 ECMAScript 5.1, 對 ECMA 6 的支援則仍在實驗中, 其原始碼寄存於 GitHub, 參考 :
二. 使用 js2py 套件 :
此為第三方套件, 可用 pip 直接安裝 :
pip install js2py
C:\Users\User>pip install js2py
Collecting js2py
Downloading Js2Py-0.71-py3-none-any.whl (1.0 MB)
Requirement already satisfied: tzlocal>=1.2 in c:\python37\lib\site-packages (from js2py) (2.0.0)
Requirement already satisfied: six>=1.10 in c:\python37\lib\site-packages (from js2py) (1.12.0)
Collecting pyjsparser>=2.5.1
Downloading pyjsparser-2.7.1.tar.gz (24 kB)
Preparing metadata (setup.py) ... done
Requirement already satisfied: pytz in c:\python37\lib\site-packages (from tzlocal>=1.2->js2py) (2018.9)
Building wheels for collected packages: pyjsparser
Building wheel for pyjsparser (setup.py) ... done
Created wheel for pyjsparser: filename=pyjsparser-2.7.1-py3-none-any.whl size=25999 sha256=91d80863115a9d83703651082c80ecf801d0cd89884593cb97c0aa9cd334ee35
Stored in directory: c:\users\user\appdata\local\pip\cache\wheels\2a\80\ac\dcd2bdbd03dd2b7b7e2bf3e5afbda6a1ab7935bbce314969da
Successfully built pyjsparser
Installing collected packages: pyjsparser, js2py
Successfully installed js2py-0.71 pyjsparser-2.7.1
使用時直接匯入 js2py 即可 :
>>> import js2py
>>> dir(js2py)
['EvalJs', 'PyJsException', '__all__', '__author__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', 'base', 'disable_pyimport', 'es6', 'eval_js', 'eval_js6', 'evaljs', 'get_file_contents', 'import_js', 'internals', 'node_import', 'parse_js', 'prototypes', 'require', 'run_file', 'translate_file', 'translate_js', 'translate_js6', 'translators', 'utils', 'write_file_contents']
可用內建函式 dir() 與 eval() 過濾 js2py 模組的成員 :
>>> members=dir(js2py)
>>> for mbr in members: # 走訪 execjs 模組成員
obj=eval('js2py.' + mbr) # 用 eval() 求值取得 js2py 成員之參考
if not mbr.startswith('_'): # 走訪所有不是 "_" 開頭的成員
print(mbr, type(obj))
EvalJs <class 'type'>
PyJsException <class 'type'>
base <class 'module'>
disable_pyimport <class 'function'>
es6 <class 'module'>
eval_js <class 'function'>
eval_js6 <class 'function'>
evaljs <class 'module'>
get_file_contents <class 'function'>
import_js <class 'function'>
internals <class 'module'>
node_import <class 'module'>
parse_js <class 'function'>
prototypes <class 'module'>
require <class 'function'>
run_file <class 'function'>
translate_file <class 'function'>
translate_js <class 'function'>
translate_js6 <class 'function'>
translators <class 'module'>
utils <class 'module'>
write_file_contents <class 'function'>
其中 eval_js() 函式用來求取 Javascript 運算式的值或函式的傳回值, 其傳入參數為 Javascript 運算式或函式字串. 注意, 傳入字串為 Javascript 語法, 因此註解須使用 //, 若使用 Python 的 # 註解會出現剖析錯誤.
求值結果若為整數, 則 eval_js() 傳回值型態為 int, 例如 :
>>> val=js2py.eval_js("1+2") # 求 1 + 2 之值
>>> type(val) # 值為整數
<class 'int'>
>>> val # 值為 3
3
求值結果若為浮點數, 則 eval_js() 的傳回值型態為 float, 例如 :
>>> val=js2py.eval_js("1.1+2.2") # 求 1.1 + 2.2 之值
>>> type(val)
<class 'float'>
>>> val
3.3000000000000003
求值結果若為字串, 則 eval_js() 的傳回值型態為 str, 例如 :
>>> val=js2py.eval_js("'The total is :' + 3.3")
>>> type(val)
<class 'str'>
>>> val
'The total is :3.3'
若傳入的運算式不只一列, 則 eval_js() 會傳回最後一個運算式的結果, 例如 :
>>> val=js2py.eval_js("""
var a=1.1;
var b=2.2;
var c= 'The total is : ' + (a + b); // 傳回此運算式的值
""")
>>> type(val)
<class 'str'>
>>> val # 傳回最後一個運算式的值
'The total is : 3.3000000000000003'
若傳入一個函式給 eval_js() 求值, 則其傳回值為一個 JsObjectWrapper 物件, 也就是將 Javascript 包裹成一個 Python 類別, 呼叫其建構式時傳入 Javascript 函式之參數即可得到其傳回值, 例如 :
>>> val=js2py.eval_js("""
function sum(a, b) {
return a + b;
}
""")
>>> type(val) # 傳回一個 Python 類別
<class 'js2py.base.JsObjectWrapper'>
>>> val
'function sum(a, b) { [python code] }'
>>> val(1, 2) # 傳入 Javascript 函式參數
3
>>> val(1.1, 2.2)
3.3000000000000003
下面是傳回字串的範例 :
>>> val=js2py.eval_js("""
function hello(msg) {
return 'Hello ' + msg;
}
""")
>>> val('World')
'Hello World'
>>> val('Tony')
'Hello Tony'
注意, 與 Pyexecjs 套件不同的是, js2py 套件目前不支援函式參數的預設值, 如果將上面的 hello(msg) 改成 hello(msg='World') 將會出現 "NotImplementedError('Defaults not supported')" 錯誤.
沒有留言:
張貼留言