2022年1月8日 星期六

Python 學習筆記 : 在 Python 中執行 Javascript 的方法 (二)

在上一篇測試中使用 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')" 錯誤. 

沒有留言 :