使用PyExecjs写的代码,放在服务器上每次执行都需要好几秒钟才能返回,经过排查发现PyExecjs的锅,官方也有如下声明:

One of cons of PyExecJS is performance. PyExecJS communicate JavaScript runtime by text and it is slow. The other cons is that it does not fully support runtime specific features.
PyV8 might be better choice for some use case.

原来PyExecjs是通过将要运行的js代码写到/tmp下面的随机文件里,然后调用相关的解释器执行该文件。没办法只能改用PyV8。
使用pip install PyV8安装怎么装都不成功,老提示找不到<v8.h>,最后发现此github上有编译好的相关文件。

安装pyv8

安装步骤:

  1. 下载相应系统的压缩文件
  2. 解压得到PyV8.py与_PyV8.so(如果so文件不是这个名字要将它改成这样)
  3. 打开python解释器,查看sys.path找到site-packages目录位置(我这里是/usr/local/lib/python3.5/site-packages)
  4. 将上面两个文件复制到site-packages目录就可以了。

pyexecjs修复

安装pyv8后,pyexecjs默认会使用pyv8运行时。pyexecjs支持的运行时及优先级如下

First-class support (runtime class is provided and tested)

  • PyV8 - A python wrapper for Google V8 engine,
  • Node.js
  • PhantomJS
  • Nashorn - Included with Oracle Java 8

Second-class support (runtime class is privided but not tested)

  • Apple JavaScriptCore - Included with Mac OS X
  • Microsoft Windows Script Host (JScript)
  • SlimerJS
  • Mozilla SpiderMonkey

相同的代码部署在服务器上运算慢的原因估计就是开发环境使用的是Apple JSCore运行时,部署在服务器上只有Nashorn。
安装完pyv8后使用pyexecjs会报如下错误:

AttributeError: module ‘contextlib’ has no attribute ‘nested’

这是由于在python3中,contextlib的nested函数被去掉了,因为with语法可以达到相同的作用,要想让pyexecjs正常运行,需要修改pyexecjs下的_pyv8runtime.py。将第51行代码
with contextlib.nested(PyV8.JSContext(), PyV8.JSEngine()) as (ctxt, engine):
改为
with PyV8.JSContext() as ctxt, PyV8.JSEngine() as engine:

Js2Py

mac os下代码可以正常运行,但部署到centos上PyV8老崩溃,提示segmentation fault。努力了两天也不行,最终找到这个js2py,它可以将js代码转成python代码,也内置了一个js运行环境。笔者将js转换成python代码后成功运行。